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.4 (Berkeley) 05/14/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 <stdio.h> 30 #include <sys/types.h> 31 #include <sys/time.h> 32 #include <syslog.h> 33 #include <kerberosIV/des.h> 34 #include <kerberosIV/krb.h> 35 #include <kerberosIV/krb_db.h> 36 #include <sys/resource.h> 37 #include <sys/signal.h> 38 #include <netinet/in.h> 39 #include "kpasswd_proto.h" 40 41 static struct kpasswd_data kpwd_data; 42 static C_Block master_key, key; 43 static Key_schedule master_key_schedule, 44 key_schedule, random_sched; 45 long mkeyversion; 46 AUTH_DAT kdata; 47 static Principal principal_data; 48 static struct update_data ud_data; 49 50 char inst[INST_SZ]; 51 char version[9]; 52 KTEXT_ST ticket; 53 54 char *progname; /* for the library */ 55 56 main() 57 { 58 struct sockaddr_in foreign; 59 int foreign_len = sizeof(foreign); 60 int rval, more; 61 static char name[] = "kpasswdd"; 62 63 static struct rlimit rl = { 0, 0 }; 64 65 progname = name; 66 openlog("kpasswdd", LOG_CONS | LOG_PID, LOG_AUTH); 67 68 signal(SIGHUP, SIG_IGN); 69 signal(SIGINT, SIG_IGN); 70 signal(SIGTSTP, SIG_IGN); 71 if (setrlimit(RLIMIT_CORE, &rl) < 0) { 72 syslog(LOG_ERR, "setrlimit: %m"); 73 exit(1); 74 } 75 76 if (getpeername(0, &foreign, &foreign_len) < 0) { 77 syslog(LOG_ERR,"getpeername: %m"); 78 exit(1); 79 } 80 81 strcpy(inst, "*"); 82 rval = krb_recvauth( 83 0L, /* options--!MUTUAL */ 84 0, /* file desc */ 85 &ticket, /* client's ticket */ 86 SERVICE, /* expected service */ 87 inst, /* expected instance */ 88 &foreign, /* foreign addr */ 89 (struct sockaddr_in *) 0, /* local addr */ 90 &kdata, /* returned krb data */ 91 "", /* service keys file */ 92 (bit_64 *) NULL, /* returned key schedule */ 93 version 94 ); 95 96 97 if (rval != KSUCCESS) { 98 syslog(LOG_ERR, "krb_recvauth: %s", krb_err_txt[rval]); 99 cleanup(); 100 exit(1); 101 } 102 103 if (*version == '\0') { 104 /* indicates error on client's side (no tickets, etc.) */ 105 cleanup(); 106 exit(0); 107 } else if (strcmp(version, "KPWDV0.1") != 0) { 108 syslog(LOG_NOTICE, 109 "kpasswdd version conflict (recv'd %s)", 110 version); 111 cleanup(); 112 exit(1); 113 } 114 115 116 /* get master key */ 117 if (kdb_get_master_key(0, master_key, master_key_schedule) != 0) { 118 syslog(LOG_ERR, "couldn't get master key"); 119 cleanup(); 120 exit(1); 121 } 122 123 mkeyversion = kdb_get_master_key(NULL, master_key, master_key_schedule); 124 125 if (mkeyversion < 0) { 126 syslog(LOG_NOTICE, "couldn't verify master key"); 127 cleanup(); 128 exit(1); 129 } 130 131 /* get principal info */ 132 rval = kerb_get_principal( 133 kdata.pname, 134 kdata.pinst, 135 &principal_data, 136 1, 137 &more 138 ); 139 140 if (rval < 0) { 141 syslog(LOG_NOTICE, 142 "error retrieving principal record for %s.%s", 143 kdata.pname, kdata.pinst); 144 cleanup(); 145 exit(1); 146 } 147 148 if (rval != 1 || (more != 0)) { 149 syslog(LOG_NOTICE, "more than 1 dbase entry for %s.%s", 150 kdata.pname, kdata.pinst); 151 cleanup(); 152 exit(1); 153 } 154 155 /* get the user's key */ 156 157 bcopy(&principal_data.key_low, key, 4); 158 bcopy(&principal_data.key_high, ((long *) key) + 1, 4); 159 kdb_encrypt_key(key, key, master_key, master_key_schedule, 160 DECRYPT); 161 key_sched(key, key_schedule); 162 des_set_key(key, key_schedule); 163 164 165 /* get random key and send it over {random} Kperson */ 166 167 random_key(kpwd_data.random_key); 168 strcpy(kpwd_data.secure_msg, SECURE_STRING); 169 if (des_write(0, &kpwd_data, sizeof(kpwd_data)) != sizeof(kpwd_data)) { 170 syslog(LOG_ERR, "error writing initial data"); 171 cleanup(); 172 exit(1); 173 } 174 175 bzero(key, sizeof(key)); 176 bzero(key_schedule, sizeof(key_schedule)); 177 178 /* now read update info: { info }Krandom */ 179 180 key_sched(kpwd_data.random_key, random_sched); 181 des_set_key(kpwd_data.random_key, random_sched); 182 if (des_read(0, &ud_data, sizeof(ud_data)) != sizeof(ud_data)) { 183 syslog(LOG_ERR, "update aborted"); 184 cleanup(); 185 exit(1); 186 } 187 188 /* validate info string by looking at the embedded string */ 189 190 if (strcmp(ud_data.secure_msg, SECURE_STRING) != 0) { 191 syslog(LOG_NOTICE, "invalid update from %s", 192 inet_ntoa(foreign.sin_addr)); 193 cleanup(); 194 exit(1); 195 } 196 197 /* produce the new key entry in the database { key }Kmaster */ 198 string_to_key(ud_data.pw, key); 199 kdb_encrypt_key(key, key, 200 master_key, master_key_schedule, 201 ENCRYPT); 202 bcopy(key, &principal_data.key_low, 4); 203 bcopy(((long *) key) + 1, 204 &principal_data.key_high, 4); 205 bzero(key, sizeof(key)); 206 principal_data.key_version++; 207 if (kerb_put_principal(&principal_data, 1)) { 208 syslog(LOG_ERR, "couldn't write new record for %s.%s", 209 principal_data.name, principal_data.instance); 210 cleanup(); 211 exit(1); 212 } 213 214 syslog(LOG_NOTICE,"wrote new password field for %s.%s from %s", 215 principal_data.name, 216 principal_data.instance, 217 inet_ntoa(foreign.sin_addr) 218 ); 219 220 send_ack(0, "Update complete.\n"); 221 cleanup(); 222 exit(0); 223 } 224 225 cleanup() 226 { 227 bzero(&kpwd_data, sizeof(kpwd_data)); 228 bzero(master_key, sizeof(master_key)); 229 bzero(master_key_schedule, sizeof(master_key_schedule)); 230 bzero(key, sizeof(key)); 231 bzero(key_schedule, sizeof(key_schedule)); 232 bzero(random_sched, sizeof(random_sched)); 233 bzero(&principal_data, sizeof(principal_data)); 234 bzero(&ud_data, sizeof(ud_data)); 235 } 236 237 send_ack(remote, msg) 238 int remote; 239 char *msg; 240 { 241 int cc; 242 cc = des_write(remote, msg, strlen(msg) + 1); 243 if (cc <= 0) { 244 syslog(LOG_ERR, "error writing ack"); 245 cleanup(); 246 exit(1); 247 } 248 } 249