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