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