/* Set the key for krb_rd_req so we can check tgt */ static int set_tgtkey(char *r, krb5_kvno kvno, krb5_boolean use_3des) { int n; static char lastrealm[REALM_SZ] = ""; static int last_kvno = 0; static krb5_boolean last_use_3des = 0; static int more; Principal p_st; Principal *p = &p_st; C_Block key; krb5_keyblock k5key; k5key.contents = NULL; if (!strcmp(lastrealm, r) && last_kvno == kvno && last_use_3des == use_3des) return (KSUCCESS); /* log("Getting key for %s", r); */ n = kerb_get_principal("krbtgt", r, p, &more, &k5key, kvno, 1, NULL); if (n == 0) return (KFAILURE); if (isflagset(p->attributes, V4_KDB_DISALLOW_ALL_TIX)) { lt = klog(L_ERR_SEXP, "V5 DISALLOW_ALL_TIX set: \"krbtgt\" \"%s\"", r); krb5_free_keyblock_contents(kdc_context, &k5key); return KFAILURE; } if (isflagset(p->attributes, V4_KDB_DISALLOW_SVR)) { lt = klog(L_ERR_SEXP, "V5 DISALLOW_SVR set: \"krbtgt\" \"%s\"", r); krb5_free_keyblock_contents(kdc_context, &k5key); return KFAILURE; } if (use_3des&&!K4KDC_ENCTYPE_OK(k5key.enctype)) { krb_set_key_krb5(kdc_context, &k5key); strncpy(lastrealm, r, sizeof(lastrealm) - 1); lastrealm[sizeof(lastrealm) - 1] = '\0'; last_kvno = kvno; last_use_3des = use_3des; } else { /* unseal tgt key from master key */ memcpy(key, &p->key_low, 4); memcpy(((krb5_ui_4 *) key) + 1, &p->key_high, 4); kdb_encrypt_key(key, key, master_key, master_key_schedule, DECRYPT); krb_set_key((char *) key, 0); strncpy(lastrealm, r, sizeof(lastrealm) - 1); lastrealm[sizeof(lastrealm) - 1] = '\0'; last_kvno = kvno; } krb5_free_keyblock_contents(kdc_context, &k5key); return (KSUCCESS); }
main() { struct sockaddr_in foreign; int foreign_len = sizeof(foreign); int rval, more; static char name[] = "kpasswdd"; static struct rlimit rl = { 0, 0 }; progname = name; openlog("kpasswdd", LOG_CONS | LOG_PID, LOG_AUTH); signal(SIGHUP, SIG_IGN); signal(SIGINT, SIG_IGN); signal(SIGTSTP, SIG_IGN); if(setrlimit(RLIMIT_CORE, &rl) < 0) { syslog(LOG_ERR, "setrlimit: %m"); exit(1); } if(getpeername(0, &foreign, &foreign_len) < 0) { syslog(LOG_ERR,"getpeername: %m"); exit(1); } strcpy(inst, "*"); rval = krb_recvauth( 0L, /* !MUTUAL */ 0, /* file desc */ &ticket, /* client's ticket */ SERVICE, /* expected service */ inst, /* expected instance */ &foreign, /* foreign addr */ (struct sockaddr_in *) 0, &kdata, "", (bit_64 *) NULL, /* key schedule */ version ); if(rval != KSUCCESS) { syslog(LOG_ERR, "krb_recvauth: %s", krb_err_txt[rval]); cleanup(); exit(1); } /* get master key */ if(kdb_get_master_key(0, master_key, master_key_schedule) != 0) { syslog(LOG_ERR, "couldn't get master key"); cleanup(); exit(1); } mkeyversion = kdb_get_master_key(master_key, master_key_schedule, NULL); if(mkeyversion < 0) { syslog(LOG_NOTICE, "couldn't verify master key"); cleanup(); exit(1); } /* get principal info */ rval = kerb_get_principal( kdata.pname, kdata.pinst, &principal_data, 1, &more ); if(rval != 1 || (more != 0)) { syslog(LOG_NOTICE, "more than 1 entry for %s.%s", kdata.pname, kdata.pinst); cleanup(); exit(1); } /* get the user's key */ bcopy(&principal_data.key_low, key, 4); bcopy(&principal_data.key_high, ((long *) key) + 1, 4); kdb_encrypt_key(key, key, master_key, master_key_schedule, DECRYPT); key_sched(key, key_schedule); des_set_key(key, key_schedule); /* get random key and send it over {random} Kperson */ random_key(kpwd_data.random_key); strcpy(kpwd_data.secure_msg, SECURE_STRING); if(des_write(0, &kpwd_data, sizeof(kpwd_data)) != sizeof(kpwd_data)) { syslog(LOG_ERR, "error writing initial data"); cleanup(); exit(1); } bzero(key, sizeof(key)); bzero(key_schedule, sizeof(key_schedule)); /* now read update info: { info }Krandom */ key_sched(kpwd_data.random_key, random_sched); des_set_key(kpwd_data.random_key, random_sched); if(des_read(0, &ud_data, sizeof(ud_data)) != sizeof(ud_data)) { syslog(LOG_ERR, "update aborted"); cleanup(); exit(1); } /* validate info string by looking at the embedded string */ if(strcmp(ud_data.secure_msg, SECURE_STRING)) { syslog(LOG_NOTICE, "invalid update from %s", inet_ntoa(foreign.sin_addr)); cleanup(); exit(1); } /* produce the new key entry in the database { key }Kmaster */ string_to_key(ud_data.pw, key); kdb_encrypt_key(key, key, master_key, master_key_schedule, ENCRYPT); bcopy(key, &principal_data.key_low, 4); bcopy(((long *) key) + 1, &principal_data.key_high, 4); bzero(key, sizeof(key)); principal_data.key_version++; if(kerb_put_principal(&principal_data, 1)) { syslog(LOG_ERR, "couldn't write new record for %s.%s", principal_data.name, principal_data.instance); cleanup(); exit(1); } syslog(LOG_NOTICE,"wrote new password field for %s.%s from %s", principal_data.name, principal_data.instance, inet_ntoa(foreign.sin_addr) ); send_ack(0, "Update complete.\n"); cleanup(); exit(0); }
static int check_princ(char *p_name, char *instance, int lifetime, Principal *p, krb5_keyblock *k5key, int issrv, krb5_deltat *k5life) { static int n; static int more; /* long trans; */ n = kerb_get_principal(p_name, instance, p, &more, k5key, 0, issrv, k5life); klog(L_ALL_REQ, "Principal: \"%s\", Instance: \"%s\" Lifetime = %d n = %d", p_name, instance, lifetime, n, 0); if (n < 0) { lt = klog(L_KRB_PERR, "Database unavailable!"); p->key_high = p->key_low = 0; hang(); } /* * if more than one p_name, pick one, randomly create a session key, * compute maximum lifetime, lookup authorizations if applicable, * and stuff into cipher. */ if (n == 0) { /* service unknown, log error, skip to next request */ lt = klog(L_ERR_UNK, "UNKNOWN \"%s\" \"%s\"", p_name, instance, 0); return KERB_ERR_PRINCIPAL_UNKNOWN; } if (more) { /* not unique, log error */ lt = klog(L_ERR_NUN, "Principal NOT UNIQUE \"%s\" \"%s\"", p_name, instance, 0); return KERB_ERR_PRINCIPAL_NOT_UNIQUE; } /* * Check our V5 stuff first. */ /* * Does the principal have REQUIRES_PWCHANGE set? */ if (isflagset(p->attributes, V4_KDB_REQUIRES_PWCHANGE)) { lt = klog(L_ERR_SEXP, "V5 REQUIRES_PWCHANGE set " "\"%s\" \"%s\"", p_name, instance); return KERB_ERR_NAME_EXP; } /* * Does the principal have DISALLOW_ALL_TIX set? */ if (isflagset(p->attributes, V4_KDB_DISALLOW_ALL_TIX)) { lt = klog(L_ERR_SEXP, "V5 DISALLOW_ALL_TIX set: " "\"%s\" \"%s\"", p_name, instance); /* Not sure of a better error to return */ return KERB_ERR_NAME_EXP; } if (isflagset(p->attributes, V4_KDB_DISALLOW_SVR)) { lt = klog(L_ERR_SEXP, "V5 DISALLOW_SVR set: " "\"%s\" \"%s\"", p_name, instance); /* Not sure of a better error to return */ return KERB_ERR_NAME_EXP; } /* * Does the principal require preauthentication? */ if ((kdc_v4 == KDC_V4_NOPREAUTH) && isflagset(p->attributes, V4_KDB_REQUIRES_PREAUTH)) { lt = klog(L_ERR_SEXP, "V5 REQUIRES_PREAUTH set: " "\"%s\" \"%s\"", p_name, instance); /* Not sure of a better error to return */ return KERB_ERR_AUTH_EXP; /* return KERB_ERR_NAME_EXP;*/ } /* If the user's key is null, we want to return an error */ if (k5key->contents != NULL && K4KDC_ENCTYPE_OK(k5key->enctype)) { if ((p->key_low == 0) && (p->key_high == 0)) { /* User has a null key */ lt = klog(L_ERR_NKY, "Null key \"%s\" \"%s\"", p_name, instance, 0); return KERB_ERR_NULL_KEY; } } /* make sure the service hasn't expired */ if (((u_long) p->exp_date != 0)&& ((u_long) p->exp_date <(u_long) kerb_time.tv_sec)) { /* service did expire, log it */ char timestr[40]; struct tm *tm; time_t t = p->exp_date; tm = localtime(&t); if (!strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S", tm)) timestr[0] = '\0'; lt = klog(L_ERR_SEXP, "EXPIRED \"%s\" \"%s\" %s", p->name, p->instance, timestr); return KERB_ERR_NAME_EXP; } /* ok is zero */ return 0; }