1 /* 2 * Copyright (c) 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 */ 17 18 #ifndef lint 19 static char sccsid[] = "@(#)kpasswdd.c 1.5 (Berkeley) 06/22/90"; 20 #endif /* not lint */ 21 22 /* 23 * kpasswdd - update a principal's passwd field in the Kerberos 24 * database. Called from inetd. 25 * K. Fall 26 * 12-Dec-88 27 */ 28 29 #include <sys/types.h> 30 #include <sys/time.h> 31 #include <sys/resource.h> 32 #include <sys/signal.h> 33 #include <netinet/in.h> 34 #include <pwd.h> 35 #include <syslog.h> 36 #include <kerberosIV/des.h> 37 #include <kerberosIV/krb.h> 38 #include <kerberosIV/krb_db.h> 39 #include <stdio.h> 40 #include "kpasswd_proto.h" 41 42 static struct kpasswd_data kpwd_data; 43 static des_cblock master_key, key; 44 static Key_schedule master_key_schedule, 45 key_schedule, random_sched; 46 long mkeyversion; 47 AUTH_DAT kdata; 48 static Principal principal_data; 49 static struct update_data ud_data; 50 51 char inst[INST_SZ]; 52 char version[9]; 53 KTEXT_ST ticket; 54 55 char *progname; /* for the library */ 56 57 main() 58 { 59 struct sockaddr_in foreign; 60 int foreign_len = sizeof(foreign); 61 int rval, more; 62 static char name[] = "kpasswdd"; 63 64 static struct rlimit rl = { 0, 0 }; 65 66 progname = name; 67 openlog("kpasswdd", LOG_CONS | LOG_PID, LOG_AUTH); 68 69 signal(SIGHUP, SIG_IGN); 70 signal(SIGINT, SIG_IGN); 71 signal(SIGTSTP, SIG_IGN); 72 if (setrlimit(RLIMIT_CORE, &rl) < 0) { 73 syslog(LOG_ERR, "setrlimit: %m"); 74 exit(1); 75 } 76 77 if (getpeername(0, &foreign, &foreign_len) < 0) { 78 syslog(LOG_ERR,"getpeername: %m"); 79 exit(1); 80 } 81 82 strcpy(inst, "*"); 83 rval = krb_recvauth( 84 0L, /* options--!MUTUAL */ 85 0, /* file desc */ 86 &ticket, /* client's ticket */ 87 SERVICE, /* expected service */ 88 inst, /* expected instance */ 89 &foreign, /* foreign addr */ 90 (struct sockaddr_in *) 0, /* local addr */ 91 &kdata, /* returned krb data */ 92 "", /* service keys file */ 93 (bit_64 *) NULL, /* returned key schedule */ 94 version 95 ); 96 97 98 if (rval != KSUCCESS) { 99 syslog(LOG_ERR, "krb_recvauth: %s", krb_err_txt[rval]); 100 cleanup(); 101 exit(1); 102 } 103 104 if (*version == '\0') { 105 /* indicates error on client's side (no tickets, etc.) */ 106 cleanup(); 107 exit(0); 108 } else if (strcmp(version, "KPWDV0.1") != 0) { 109 syslog(LOG_NOTICE, 110 "kpasswdd version conflict (recv'd %s)", 111 version); 112 cleanup(); 113 exit(1); 114 } 115 116 117 /* get master key */ 118 if (kdb_get_master_key(0, master_key, master_key_schedule) != 0) { 119 syslog(LOG_ERR, "couldn't get master key"); 120 cleanup(); 121 exit(1); 122 } 123 124 mkeyversion = kdb_get_master_key(NULL, master_key, master_key_schedule); 125 126 if (mkeyversion < 0) { 127 syslog(LOG_NOTICE, "couldn't verify master key"); 128 cleanup(); 129 exit(1); 130 } 131 132 /* get principal info */ 133 rval = kerb_get_principal( 134 kdata.pname, 135 kdata.pinst, 136 &principal_data, 137 1, 138 &more 139 ); 140 141 if (rval < 0) { 142 syslog(LOG_NOTICE, 143 "error retrieving principal record for %s.%s", 144 kdata.pname, kdata.pinst); 145 cleanup(); 146 exit(1); 147 } 148 149 if (rval != 1 || (more != 0)) { 150 syslog(LOG_NOTICE, "more than 1 dbase entry for %s.%s", 151 kdata.pname, kdata.pinst); 152 cleanup(); 153 exit(1); 154 } 155 156 /* get the user's key */ 157 158 bcopy(&principal_data.key_low, key, 4); 159 bcopy(&principal_data.key_high, ((long *) key) + 1, 4); 160 kdb_encrypt_key(key, key, master_key, master_key_schedule, 161 DECRYPT); 162 key_sched(key, key_schedule); 163 des_set_key(key, key_schedule); 164 165 166 /* get random key and send it over {random} Kperson */ 167 168 random_key(kpwd_data.random_key); 169 strcpy(kpwd_data.secure_msg, SECURE_STRING); 170 if (des_write(0, &kpwd_data, sizeof(kpwd_data)) != sizeof(kpwd_data)) { 171 syslog(LOG_ERR, "error writing initial data"); 172 cleanup(); 173 exit(1); 174 } 175 176 bzero(key, sizeof(key)); 177 bzero(key_schedule, sizeof(key_schedule)); 178 179 /* now read update info: { info }Krandom */ 180 181 key_sched(kpwd_data.random_key, random_sched); 182 des_set_key(kpwd_data.random_key, random_sched); 183 if (des_read(0, &ud_data, sizeof(ud_data)) != sizeof(ud_data)) { 184 syslog(LOG_ERR, "update aborted"); 185 cleanup(); 186 exit(1); 187 } 188 189 /* validate info string by looking at the embedded string */ 190 191 if (strcmp(ud_data.secure_msg, SECURE_STRING) != 0) { 192 syslog(LOG_NOTICE, "invalid update from %s", 193 inet_ntoa(foreign.sin_addr)); 194 cleanup(); 195 exit(1); 196 } 197 198 /* produce the new key entry in the database { key }Kmaster */ 199 string_to_key(ud_data.pw, key); 200 kdb_encrypt_key(key, key, 201 master_key, master_key_schedule, 202 ENCRYPT); 203 bcopy(key, &principal_data.key_low, 4); 204 bcopy(((long *) key) + 1, 205 &principal_data.key_high, 4); 206 bzero(key, sizeof(key)); 207 principal_data.key_version++; 208 if (kerb_put_principal(&principal_data, 1)) { 209 syslog(LOG_ERR, "couldn't write new record for %s.%s", 210 principal_data.name, principal_data.instance); 211 cleanup(); 212 exit(1); 213 } 214 215 syslog(LOG_NOTICE,"wrote new password field for %s.%s from %s", 216 principal_data.name, 217 principal_data.instance, 218 inet_ntoa(foreign.sin_addr) 219 ); 220 221 send_ack(0, "Update complete.\n"); 222 cleanup(); 223 exit(0); 224 } 225 226 cleanup() 227 { 228 bzero(&kpwd_data, sizeof(kpwd_data)); 229 bzero(master_key, sizeof(master_key)); 230 bzero(master_key_schedule, sizeof(master_key_schedule)); 231 bzero(key, sizeof(key)); 232 bzero(key_schedule, sizeof(key_schedule)); 233 bzero(random_sched, sizeof(random_sched)); 234 bzero(&principal_data, sizeof(principal_data)); 235 bzero(&ud_data, sizeof(ud_data)); 236 } 237 238 send_ack(remote, msg) 239 int remote; 240 char *msg; 241 { 242 int cc; 243 cc = des_write(remote, msg, strlen(msg) + 1); 244 if (cc <= 0) { 245 syslog(LOG_ERR, "error writing ack"); 246 cleanup(); 247 exit(1); 248 } 249 } 250