void kerberos4_is(Authenticator *ap, unsigned char *data, int cnt) { struct sockaddr_in addr; char realm[REALM_SZ]; char instance[INST_SZ]; int r; int addr_len; if (cnt-- < 1) return; switch (*data++) { case KRB_AUTH: if (krb_get_lrealm(realm, 1) != KSUCCESS) { Data(ap, KRB_REJECT, (void *)"No local V4 Realm.", -1); auth_finished(ap, AUTH_REJECT); if (auth_debug_mode) printf("No local realm\r\n"); return; } memmove(auth.dat, data, auth.length = cnt); if (auth_debug_mode) { printf("Got %d bytes of authentication data\r\n", cnt); printf("CK: %d:", kerberos4_cksum(auth.dat, auth.length)); printd(auth.dat, auth.length); printf("\r\n"); } k_getsockinst(0, instance, sizeof(instance)); addr_len = sizeof(addr); if(getpeername(0, (struct sockaddr *)&addr, &addr_len) < 0) { if(auth_debug_mode) printf("getpeername failed\r\n"); Data(ap, KRB_REJECT, "getpeername failed", -1); auth_finished(ap, AUTH_REJECT); return; } r = krb_rd_req(&auth, KRB_SERVICE_NAME, instance, addr.sin_addr.s_addr, &adat, ""); if (r) { if (auth_debug_mode) printf("Kerberos failed him as %s\r\n", name); Data(ap, KRB_REJECT, (void *)krb_get_err_text(r), -1); auth_finished(ap, AUTH_REJECT); return; } /* save the session key */ memmove(session_key, adat.session, sizeof(adat.session)); krb_kntoln(&adat, name); if (UserNameRequested && !kuserok(&adat, UserNameRequested)){ char ts[MAXPATHLEN]; struct passwd *pw = getpwnam(UserNameRequested); if(pw){ snprintf(ts, sizeof(ts), "%s%u", TKT_ROOT, (unsigned)pw->pw_uid); setenv("KRBTKFILE", ts, 1); } Data(ap, KRB_ACCEPT, NULL, 0); } else { char *msg; asprintf (&msg, "user `%s' is not authorized to " "login as `%s'", krb_unparse_name_long(adat.pname, adat.pinst, adat.prealm), UserNameRequested ? UserNameRequested : "<nobody>"); if (msg == NULL) Data(ap, KRB_REJECT, NULL, 0); else { Data(ap, KRB_REJECT, (void *)msg, -1); free(msg); } } auth_finished(ap, AUTH_USER); break; case KRB_CHALLENGE: #ifndef ENCRYPTION Data(ap, KRB_RESPONSE, NULL, 0); #else if(!VALIDKEY(session_key)){ Data(ap, KRB_RESPONSE, NULL, 0); break; } des_key_sched(&session_key, sched); { des_cblock d_block; int i; Session_Key skey; memmove(d_block, data, sizeof(d_block)); /* make a session key for encryption */ des_ecb_encrypt(&d_block, &session_key, sched, 1); skey.type=SK_DES; skey.length=8; skey.data=session_key; encrypt_session_key(&skey, 1); /* decrypt challenge, add one and encrypt it */ des_ecb_encrypt(&d_block, &challenge, sched, 0); for (i = 7; i >= 0; i--) if(++challenge[i] != 0) break; des_ecb_encrypt(&challenge, &challenge, sched, 1); Data(ap, KRB_RESPONSE, (void *)challenge, sizeof(challenge)); } #endif break; case KRB_FORWARD: { des_key_schedule ks; unsigned char netcred[sizeof(CREDENTIALS)]; CREDENTIALS cred; int ret; if(cnt > sizeof(cred)) abort(); des_set_key(&session_key, ks); des_pcbc_encrypt((void*)data, (void*)netcred, cnt, ks, &session_key, DES_DECRYPT); unpack_cred(netcred, cnt, &cred); { if(strcmp(cred.service, KRB_TICKET_GRANTING_TICKET) || strncmp(cred.instance, cred.realm, sizeof(cred.instance)) || cred.lifetime < 0 || cred.lifetime > 255 || cred.kvno < 0 || cred.kvno > 255 || cred.issue_date < 0 || cred.issue_date > time(0) + CLOCK_SKEW || strncmp(cred.pname, adat.pname, sizeof(cred.pname)) || strncmp(cred.pinst, adat.pinst, sizeof(cred.pname))){ Data(ap, KRB_FORWARD_REJECT, "Bad credentials", -1); }else{ if((ret = tf_setup(&cred, cred.pname, cred.pinst)) == KSUCCESS){ struct passwd *pw = getpwnam(UserNameRequested); if (pw) chown(tkt_string(), pw->pw_uid, pw->pw_gid); Data(ap, KRB_FORWARD_ACCEPT, 0, 0); } else{ Data(ap, KRB_FORWARD_REJECT, krb_get_err_text(ret), -1); } } } memset(data, 0, cnt); memset(ks, 0, sizeof(ks)); memset(&cred, 0, sizeof(cred)); } break; default: if (auth_debug_mode) printf("Unknown Kerberos option %d\r\n", data[-1]); Data(ap, KRB_REJECT, 0, 0); break; } }
static void store_tickets(struct passwd *pwd, int ticket_newfiles, int ticket_store, int token_install) { char cc_file[MAXPATHLEN]; krb5_ccache ccache_store; #ifdef KRB524 int get_krb4_ticket = 0; char krb4_ticket_file[MAXPATHLEN]; #endif if (ticket_newfiles) snprintf(cc_file, sizeof(cc_file), "FILE:/tmp/krb5cc_%d", pwd->pw_uid); else snprintf(cc_file, sizeof(cc_file), "%s", krb5_cc_default_name(context)); if (ticket_store) { ret = krb5_cc_resolve(context, cc_file, &ccache_store); if (ret != 0) { krb5_syslog(context, LOG_ERR, ret, "krb5_cc_gen_new"); exit(1); } ret = krb5_cc_copy_cache(context, ccache, ccache_store); if (ret != 0) krb5_syslog(context, LOG_ERR, ret, "krb5_cc_copy_cache"); chown(krb5_cc_get_name(context, ccache_store), pwd->pw_uid, pwd->pw_gid); fprintf(back, BI_SETENV " KRB5CCNAME %s:%s\n", krb5_cc_get_type(context, ccache_store), krb5_cc_get_name(context, ccache_store)); #ifdef KRB524 get_krb4_ticket = krb5_config_get_bool_default (context, NULL, get_krb4_ticket, "libdefaults", "krb4_get_tickets", NULL); if (get_krb4_ticket) { CREDENTIALS c; krb5_creds cred; krb5_cc_cursor cursor; ret = krb5_cc_start_seq_get(context, ccache, &cursor); if (ret != 0) { krb5_syslog(context, LOG_ERR, ret, "start seq"); exit(1); } ret = krb5_cc_next_cred(context, ccache, &cursor, &cred); if (ret != 0) { krb5_syslog(context, LOG_ERR, ret, "next cred"); exit(1); } ret = krb5_cc_end_seq_get(context, ccache, &cursor); if (ret != 0) { krb5_syslog(context, LOG_ERR, ret, "end seq"); exit(1); } ret = krb524_convert_creds_kdc_ccache(context, ccache, &cred, &c); if (ret != 0) { krb5_syslog(context, LOG_ERR, ret, "convert"); } else { snprintf(krb4_ticket_file, sizeof(krb4_ticket_file), "%s%d", TKT_ROOT, pwd->pw_uid); krb_set_tkt_string(krb4_ticket_file); tf_setup(&c, c.pname, c.pinst); chown(krb4_ticket_file, pwd->pw_uid, pwd->pw_gid); } } #endif } /* Need to chown the ticket file */ #ifdef KRB524 if (get_krb4_ticket) fprintf(back, BI_SETENV " KRBTKFILE %s\n", krb4_ticket_file); #endif }
static int verify_krb5(struct passwd *pwd, char *password, int32_t *exp, int quiet) { krb5_context context; krb5_error_code ret; krb5_ccache ccache; krb5_principal principal; ret = krb5_init_context(&context); if (ret) { syslog(LOG_AUTH|LOG_DEBUG, "krb5_init_context failed: %d", ret); goto out; } ret = krb5_parse_name (context, pwd->pw_name, &principal); if (ret) { syslog(LOG_AUTH|LOG_DEBUG, "krb5_parse_name: %s", krb5_get_err_text(context, ret)); goto out; } set_krb5ccname(pwd->pw_uid); ret = krb5_cc_resolve(context, krb5ccname, &ccache); if(ret) { syslog(LOG_AUTH|LOG_DEBUG, "krb5_cc_resolve: %s", krb5_get_err_text(context, ret)); goto out; } ret = krb5_verify_user_lrealm(context, principal, ccache, password, TRUE, NULL); if(ret) { syslog(LOG_AUTH|LOG_DEBUG, "krb5_verify_user: %s", krb5_get_err_text(context, ret)); goto out; } if(chown(krb5_cc_get_name(context, ccache), pwd->pw_uid, pwd->pw_gid)) { syslog(LOG_AUTH|LOG_DEBUG, "chown: %s", krb5_get_err_text(context, errno)); goto out; } #ifdef KRB4 { krb5_realm realm = NULL; krb5_boolean get_v4_tgt; krb5_get_default_realm(context, &realm); krb5_appdefault_boolean(context, "afskauthlib", realm, "krb4_get_tickets", FALSE, &get_v4_tgt); if (get_v4_tgt) { CREDENTIALS c; krb5_creds mcred, cred; krb5_cc_clear_mcred(&mcred); krb5_make_principal(context, &mcred.server, realm, "krbtgt", realm, NULL); ret = krb5_cc_retrieve_cred(context, ccache, 0, &mcred, &cred); if(ret == 0) { ret = krb524_convert_creds_kdc_ccache(context, ccache, &cred, &c); if(ret) krb5_warn(context, ret, "converting creds"); else { set_krbtkfile(pwd->pw_uid); tf_setup(&c, c.pname, c.pinst); } memset(&c, 0, sizeof(c)); krb5_free_cred_contents(context, &cred); } else syslog(LOG_AUTH|LOG_DEBUG, "krb5_cc_retrieve_cred: %s", krb5_get_err_text(context, ret)); krb5_free_principal(context, mcred.server); } free (realm); if (!pag_set && k_hasafs()) { k_setpag(); pag_set = 1; } if (pag_set) krb5_afslog_uid_home(context, ccache, NULL, NULL, pwd->pw_uid, pwd->pw_dir); } #endif out: if(ret && !quiet) printf ("%s\n", krb5_get_err_text (context, ret)); return ret; }