1 2 /* 3 * Copyright (c) 1989 The Regents of the University of California. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms are permitted 7 * provided that the above copyright notice and this paragraph are 8 * duplicated in all such forms and that any documentation, 9 * advertising materials, and other materials related to such 10 * distribution and use acknowledge that the software was developed 11 * by the University of California, Berkeley. The name of the 12 * University may not be used to endorse or promote products derived 13 * from this software without specific prior written permission. 14 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 17 */ 18 19 #ifndef lint 20 static char sccsid[] = "@(#)registerd.c 1.4 (Berkeley) 05/17/89"; 21 #endif /* not lint */ 22 23 #include <sys/types.h> 24 #include <sys/time.h> 25 #include <sys/signal.h> 26 #include <sys/resource.h> 27 #include <sys/param.h> 28 #include <sys/file.h> 29 #include <netinet/in.h> 30 #include <stdio.h> 31 #include <syslog.h> 32 #include <kerberos/krb.h> 33 #include <kerberos/krb_db.h> 34 #include "register_proto.h" 35 36 #define SKEYFILE "/kerberos/update.key%s" 37 #define KBUFSIZ (sizeof(struct keyfile_data)) 38 #define CRYPT 0x00 39 #define CLEAR 0x01 40 41 char *progname; 42 struct sockaddr_in sin; 43 char msgbuf[BUFSIZ]; 44 45 int die(); 46 47 main(argc, argv) 48 char **argv; 49 { 50 int kf; 51 char keyfile[MAXPATHLEN]; 52 static Key_schedule schedule; 53 u_char code; 54 char keybuf[KBUFSIZ]; 55 int retval, sval; 56 struct keyfile_data *kfile; 57 static struct rlimit rl = { 0, 0 }; 58 59 openlog("registerd", LOG_PID, LOG_AUTH); 60 61 progname = argv[0]; 62 63 signal(SIGHUP, SIG_IGN); 64 signal(SIGINT, SIG_IGN); 65 signal(SIGTSTP, SIG_IGN); 66 signal(SIGPIPE, die); 67 if(setrlimit(RLIMIT_CORE, &rl) < 0) { 68 syslog(LOG_ERR, "setrlimit: %m"); 69 exit(1); 70 } 71 72 73 /* figure out who we are talking to */ 74 75 sval = sizeof(sin); 76 if(getpeername(0, (struct sockaddr *) &sin, &sval) < 0) { 77 syslog(LOG_ERR, "getpeername: %m"); 78 exit(1); 79 } 80 81 /* get encryption key */ 82 83 (void) sprintf(keyfile, SKEYFILE, inet_ntoa(sin.sin_addr)); 84 if((kf = open(keyfile, O_RDONLY)) < 0) { 85 syslog(LOG_ERR, "error opening Kerberos update keyfile (%s): %m", keyfile); 86 (void) sprintf(msgbuf, "couldn't open session keyfile for your host"); 87 send_packet(msgbuf, CLEAR); 88 exit(1); 89 } 90 91 if(read(kf, keybuf, KBUFSIZ) != KBUFSIZ) { 92 syslog(LOG_ERR, "wrong read size of Kerberos update keyfile"); 93 (void) sprintf(msgbuf, 94 "couldn't read session key from your host's keyfile"); 95 send_packet(msgbuf, CLEAR); 96 exit(1); 97 } 98 (void) sprintf(msgbuf, GOTKEY_MSG); 99 send_packet(msgbuf, CLEAR); 100 kfile = (struct keyfile_data *) keybuf; 101 key_sched(kfile->kf_key, schedule); 102 des_set_key(kfile->kf_key, schedule); 103 104 /* read the command code byte */ 105 106 if(des_read(0, &code, 1) == 1) { 107 108 switch(code) { 109 case APPEND_DB: 110 retval = do_append(); 111 break; 112 case ABORT: 113 cleanup(); 114 close(0); 115 exit(0); 116 default: 117 retval = KFAILURE; 118 syslog(LOG_NOTICE, 119 "invalid command code on db update (0x%x)", code); 120 } 121 122 } else { 123 retval = KFAILURE; 124 syslog(LOG_ERR, "couldn't read command code on Kerberos update"); 125 } 126 127 code = (u_char) retval; 128 if(code != KSUCCESS) { 129 (void) sprintf(msgbuf, "%s", krb_err_txt[code]); 130 send_packet(msgbuf,CRYPT); 131 } else { 132 (void) sprintf(msgbuf, "Update complete."); 133 send_packet(msgbuf, CRYPT); 134 } 135 cleanup(); 136 close(0); 137 exit(0); 138 } 139 140 #define MAX_PRINCIPAL 10 141 static Principal principal_data[MAX_PRINCIPAL]; 142 static C_Block key, master_key; 143 static Key_schedule master_key_schedule; 144 int 145 do_append() 146 { 147 Principal default_princ; 148 char input_name[ANAME_SZ]; 149 char input_instance[INST_SZ]; 150 int j,n, more; 151 long mkeyversion; 152 153 154 155 /* get master key from MKEYFILE */ 156 if(kdb_get_master_key(0, master_key, master_key_schedule) != 0) { 157 syslog(LOG_ERR, "couldn't get master key"); 158 return(KFAILURE); 159 } 160 161 mkeyversion = kdb_verify_master_key(master_key, master_key_schedule, NULL); 162 if(mkeyversion < 0) { 163 syslog(LOG_ERR, "couldn't validate master key"); 164 return(KFAILURE); 165 } 166 167 n = kerb_get_principal(KERB_DEFAULT_NAME, KERB_DEFAULT_INST, 168 &default_princ, 1, &more); 169 170 if(n != 1) { 171 syslog(LOG_ERR, "couldn't get default principal"); 172 return(KFAILURE); 173 } 174 175 /* 176 * get principal name, instance, and password from network. 177 * convert password to key and store it 178 */ 179 180 if(net_get_principal(input_name, input_instance, key) != 0) { 181 return(KFAILURE); 182 } 183 184 185 j = kerb_get_principal( 186 input_name, 187 input_instance, 188 principal_data, 189 MAX_PRINCIPAL, 190 &more 191 ); 192 193 if(j != 0) { 194 /* already in database, no update */ 195 syslog(LOG_NOTICE, "attempt to add duplicate entry for principal %s.%s", 196 input_name, input_instance); 197 return(KDC_PR_N_UNIQUE); 198 } 199 200 /* 201 * set up principal's name, instance 202 */ 203 204 strcpy(principal_data[0].name, input_name); 205 strcpy(principal_data[0].instance, input_instance); 206 principal_data[0].old = NULL; 207 208 209 /* and the expiration date and version #s */ 210 211 principal_data[0].exp_date = default_princ.exp_date; 212 strcpy(principal_data[0].exp_date_txt, default_princ.exp_date_txt); 213 principal_data[0].max_life = default_princ.max_life; 214 principal_data[0].attributes = default_princ.attributes; 215 principal_data[0].kdc_key_ver = default_princ.kdc_key_ver; 216 217 218 /* and the key */ 219 220 kdb_encrypt_key(key, key, master_key, master_key_schedule, 221 ENCRYPT); 222 bcopy(key, &principal_data[0].key_low, 4); 223 bcopy(((long *) key) + 1, &principal_data[0].key_high,4); 224 bzero(key, sizeof(key)); 225 226 principal_data[0].key_version = 1; /* 1st entry */ 227 if(kerb_put_principal(&principal_data[0], 1)) { 228 syslog(LOG_INFO, "Kerberos update failure: put_principal failed"); 229 return(KFAILURE); 230 } 231 232 syslog(LOG_NOTICE, "Kerberos update: wrote new record for %s.%s from %s", 233 principal_data[0].name, 234 principal_data[0].instance, 235 inet_ntoa(sin.sin_addr) 236 ); 237 238 return(KSUCCESS); 239 240 } 241 242 send_packet(msg,flag) 243 char *msg; 244 int flag; 245 { 246 int len = strlen(msg); 247 msg[len++] = '\n'; 248 msg[len] = '\0'; 249 if (len > sizeof(msgbuf)) { 250 syslog(LOG_ERR, "send_packet: invalid msg size"); 251 return; 252 } 253 if (flag == CRYPT) { 254 if (des_write(0, msg, len) != len) 255 syslog(LOG_ERR, "couldn't write reply message"); 256 } else if (flag == CLEAR) { 257 if (write(0, msg, len) != len) 258 syslog(LOG_ERR, "couldn't write reply message"); 259 } else 260 syslog(LOG_ERR, "send_packet: invalid flag (%d)", flag); 261 262 } 263 264 net_get_principal(pname, iname, keyp) 265 char *pname, *iname; 266 C_Block *keyp; 267 { 268 int cc; 269 static char password[255]; 270 271 cc = des_read(0, pname, ANAME_SZ); 272 if(cc != ANAME_SZ) { 273 syslog(LOG_ERR, "couldn't get principal name"); 274 return(-1); 275 } 276 277 cc = des_read(0, iname, INST_SZ); 278 if(cc != INST_SZ) { 279 syslog(LOG_ERR, "couldn't get instance name"); 280 return(-1); 281 } 282 283 cc = des_read(0, password, 255); 284 if(cc != 255) { 285 syslog(LOG_ERR, "couldn't get password"); 286 bzero(password, 255); 287 return(-1); 288 } 289 290 string_to_key(password, *keyp); 291 bzero(password, 255); 292 return(0); 293 } 294 295 cleanup() 296 { 297 bzero(master_key, sizeof(master_key)); 298 bzero(key, sizeof(key)); 299 bzero(master_key_schedule, sizeof(master_key_schedule)); 300 } 301 302 die() 303 { 304 syslog(LOG_ERR, "remote end died (SIGPIPE)"); 305 cleanup(); 306 exit(1); 307 } 308