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