krb5_error_code krb5_ldap_parse_principal_name(char *i_princ_name, char **o_princ_name) { const char *at_rlm_name, *p; struct k5buf buf; at_rlm_name = strrchr(i_princ_name, '@'); if (!at_rlm_name) { *o_princ_name = strdup(i_princ_name); if (!o_princ_name) return ENOMEM; } else { krb5int_buf_init_dynamic(&buf); for (p = i_princ_name; p < at_rlm_name; p++) { if (*p == '@') krb5int_buf_add(&buf, "\\"); krb5int_buf_add_len(&buf, p, 1); } krb5int_buf_add(&buf, at_rlm_name); *o_princ_name = krb5int_buf_data(&buf); if (!*o_princ_name) return ENOMEM; } return 0; }
static char *handle_sam_labels(krb5_sam_challenge *sc) { char *label = sc->sam_challenge_label.data; unsigned int label_len = sc->sam_challenge_label.length; char *prompt = sc->sam_response_prompt.data; unsigned int prompt_len = sc->sam_response_prompt.length; char *challenge = sc->sam_challenge.data; unsigned int challenge_len = sc->sam_challenge.length; struct k5buf buf; if (sc->sam_cksum.length == 0) { /* or invalid -- but lets just handle presence now XXX */ switch (sc->sam_type) { case PA_SAM_TYPE_ENIGMA: /* Enigma Logic */ label = "Challenge for Enigma Logic mechanism"; break; case PA_SAM_TYPE_DIGI_PATH: /* Digital Pathways */ case PA_SAM_TYPE_DIGI_PATH_HEX: /* Digital Pathways */ label = "Challenge for Digital Pathways mechanism"; break; case PA_SAM_TYPE_ACTIVCARD_DEC: /* Digital Pathways */ case PA_SAM_TYPE_ACTIVCARD_HEX: /* Digital Pathways */ label = "Challenge for Activcard mechanism"; break; case PA_SAM_TYPE_SKEY_K0: /* S/key where KDC has key 0 */ label = "Challenge for Enhanced S/Key mechanism"; break; case PA_SAM_TYPE_SKEY: /* Traditional S/Key */ label = "Challenge for Traditional S/Key mechanism"; break; case PA_SAM_TYPE_SECURID: /* Security Dynamics */ label = "Challenge for Security Dynamics mechanism"; break; case PA_SAM_TYPE_SECURID_PREDICT: /* predictive Security Dynamics */ label = "Challenge for Security Dynamics mechanism"; break; } prompt = "Passcode"; label_len = strlen(label); prompt_len = strlen(prompt); } /* example: Challenge for Digital Pathways mechanism: [134591] Passcode: */ krb5int_buf_init_dynamic(&buf); if (challenge_len) { krb5int_buf_add_len(&buf, label, label_len); krb5int_buf_add(&buf, ": ["); krb5int_buf_add_len(&buf, challenge, challenge_len); krb5int_buf_add(&buf, "]\n"); } krb5int_buf_add_len(&buf, prompt, prompt_len); krb5int_buf_add(&buf, ": "); return krb5int_buf_data(&buf); }
krb5_error_code KRB5_CALLCONV krb5_get_init_creds_opt_set_fast_ccache(krb5_context context, krb5_get_init_creds_opt *opt, krb5_ccache ccache) { krb5_error_code retval = 0; struct k5buf buf; char *cc_name; krb5int_buf_init_dynamic(&buf); krb5int_buf_add(&buf, krb5_cc_get_type(context, ccache)); krb5int_buf_add(&buf, ":"); krb5int_buf_add(&buf, krb5_cc_get_name(context, ccache)); cc_name = krb5int_buf_data(&buf); if (cc_name) retval = krb5_get_init_creds_opt_set_fast_ccache_name(context, opt, cc_name); else retval = ENOMEM; krb5int_free_buf(&buf); return retval; }
krb5_error_code krb5_try_realm_txt_rr(const char *prefix, const char *name, char **realm) { krb5_error_code retval = KRB5_ERR_HOST_REALM_UNKNOWN; const unsigned char *p, *base; char host[MAXDNAME]; int ret, rdlen, len; struct krb5int_dns_state *ds = NULL; struct k5buf buf; /* * Form our query, and send it via DNS */ krb5int_buf_init_fixed(&buf, host, sizeof(host)); if (name == NULL || name[0] == '\0') { krb5int_buf_add(&buf, prefix); } else { krb5int_buf_add_fmt(&buf, "%s.%s", prefix, name); /* Realm names don't (normally) end with ".", but if the query doesn't end with "." and doesn't get an answer as is, the resolv code will try appending the local domain. Since the realm names are absolutes, let's stop that. But only if a name has been specified. If we are performing a search on the prefix alone then the intention is to allow the local domain or domain search lists to be expanded. */ len = krb5int_buf_len(&buf); if (len > 0 && host[len - 1] != '.') krb5int_buf_add(&buf, "."); } if (krb5int_buf_data(&buf) == NULL) return KRB5_ERR_HOST_REALM_UNKNOWN; ret = krb5int_dns_init(&ds, host, C_IN, T_TXT); if (ret < 0) goto errout; ret = krb5int_dns_nextans(ds, &base, &rdlen); if (ret < 0 || base == NULL) goto errout; p = base; if (!INCR_OK(base, rdlen, p, 1)) goto errout; len = *p++; *realm = malloc((size_t)len + 1); if (*realm == NULL) { retval = ENOMEM; goto errout; } strncpy(*realm, (const char *)p, (size_t)len); (*realm)[len] = '\0'; /* Avoid a common error. */ if ( (*realm)[len-1] == '.' ) (*realm)[len-1] = '\0'; retval = 0; errout: if (ds != NULL) { krb5int_dns_fini(ds); ds = NULL; } return retval; }
static void test_hmac() { krb5_keyblock key; krb5_data in, out; char outbuf[20]; char stroutbuf[80]; krb5_error_code err; unsigned int i, j; int lose = 0; struct k5buf buf; /* RFC 2202 test vector. */ static const struct hmac_test md5tests[] = { { 16, { 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, }, 8, "Hi There", "0x9294727a3638bb1c13f48ef8158bfc9d" }, { 4, "Jefe", 28, "what do ya want for nothing?", "0x750c783e6ab0b503eaa86e310a5db738" }, { 16, { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa }, 50, { 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, }, "0x56be34521d144c88dbb8c733f0e8b3f6" }, { 25, { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19 }, 50, { 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, }, "0x697eaf0aca3a3aea3a75164746ffaa79" }, { 16, { 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c }, 20, "Test With Truncation", "0x56461ef2342edc00f9bab995690efd4c" }, { 80, { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, }, 54, "Test Using Larger Than Block-Size Key - Hash Key First", "0x6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd" }, { 80, { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, }, 73, "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", "0x6f630fad67cda0ee1fb1f562db3aa53e" }, }; for (i = 0; i < sizeof(md5tests)/sizeof(md5tests[0]); i++) { key.contents = md5tests[i].key; key.length = md5tests[i].key_len; in.data = md5tests[i].data; in.length = md5tests[i].data_len; out.data = outbuf; out.length = 20; printf("\nTest #%d:\n", i+1); err = hmac1(&krb5int_hash_md5, &key, &in, &out); if (err) { com_err(whoami, err, "computing hmac"); exit(1); } krb5int_buf_init_fixed(&buf, stroutbuf, sizeof(stroutbuf)); krb5int_buf_add(&buf, "0x"); for (j = 0; j < out.length; j++) krb5int_buf_add_fmt(&buf, "%02x", 0xff & outbuf[j]); if (krb5int_buf_data(&buf) == NULL) abort(); if (strcmp(stroutbuf, md5tests[i].hexdigest)) { printf("*** CHECK FAILED!\n" "\tReturned: %s.\n" "\tExpected: %s.\n", stroutbuf, md5tests[i].hexdigest); lose++; } else printf("Matches expected result.\n"); } /* Do again with SHA-1 tests.... */ if (lose) { printf("%d failures; exiting.\n", lose); exit(1); } }
static krb5_error_code decode_ad_policy_info(const krb5_data *data, char **msg_out) { struct ad_policy_info policy; uint64_t password_days; const char *p; char *msg; struct k5buf buf; *msg_out = NULL; if (data->length != AD_POLICY_INFO_LENGTH) return 0; p = data->data; policy.zero_bytes = load_16_be(p); p += 2; /* first two bytes are zeros */ if (policy.zero_bytes != 0) return 0; /* Read in the rest of structure */ policy.min_length_password = load_32_be(p); p += 4; policy.password_history = load_32_be(p); p += 4; policy.password_properties = load_32_be(p); p += 4; policy.expire = load_64_be(p); p += 8; policy.min_passwordage = load_64_be(p); p += 8; /* Check that we processed exactly the expected number of bytes. */ assert(p == data->data + AD_POLICY_INFO_LENGTH); krb5int_buf_init_dynamic(&buf); /* * Update src/tests/misc/test_chpw_message.c if changing these strings! */ if (policy.password_properties & AD_POLICY_COMPLEX) { krb5int_buf_add(&buf, _("The password must include numbers or symbols. " "Don't include any part of your name in the " "password.")); } if (policy.min_length_password > 0) { add_spaces(&buf); krb5int_buf_add_fmt(&buf, ngettext("The password must contain at least %d " "character.", "The password must contain at least %d " "characters.", policy.min_length_password), policy.min_length_password); } if (policy.password_history) { add_spaces(&buf); krb5int_buf_add_fmt(&buf, ngettext("The password must be different from the " "previous password.", "The password must be different from the " "previous %d passwords.", policy.password_history), policy.password_history); } if (policy.min_passwordage) { password_days = policy.min_passwordage / AD_POLICY_TIME_TO_DAYS; if (password_days == 0) password_days = 1; add_spaces(&buf); krb5int_buf_add_fmt(&buf, ngettext("The password can only be changed once a " "day.", "The password can only be changed every " "%d days.", (int)password_days), (int)password_days); } msg = krb5int_buf_data(&buf); if (msg == NULL) return ENOMEM; if (*msg != '\0') *msg_out = msg; else free(msg); return 0; }
/* If buf already contains one or more sentences, add spaces to separate them * from the next sentence. */ static void add_spaces(struct k5buf *buf) { if (krb5int_buf_len(buf) > 0) krb5int_buf_add(buf, " "); }
void krb5int_debug_fprint (const char *fmt, ...) { #ifdef DEBUG va_list args; /* Temporaries for variable arguments, etc. */ krb5_error_code kerr; int err; fd_set *rfds, *wfds, *xfds; int i; int maxfd; struct timeval *tv; struct addrinfo *ai; const krb5_data *d; char addrbuf[NI_MAXHOST], portbuf[NI_MAXSERV]; const char *p; #ifndef max #define max(a,b) ((a) > (b) ? (a) : (b)) #endif char tmpbuf[max(NI_MAXHOST + NI_MAXSERV + 30, 200)]; struct k5buf buf; if (!krb5int_debug_sendto_kdc) return; va_start(args, fmt); #define putf(FMT,X) (snprintf(tmpbuf,sizeof(tmpbuf),FMT,X),putstr(tmpbuf)) for (; *fmt; fmt++) { if (*fmt != '%') { const char *fmt2; size_t len; for (fmt2 = fmt+1; *fmt2; fmt2++) if (*fmt2 == '%') break; len = fmt2 - fmt; put(fmt, len); fmt += len - 1; /* then fmt++ in loop header */ continue; } /* After this, always processing a '%' sequence. */ fmt++; switch (*fmt) { case 0: default: abort(); case 'E': /* %E => krb5_error_code */ kerr = va_arg(args, krb5_error_code); snprintf(tmpbuf, sizeof(tmpbuf), "%lu/", (unsigned long) kerr); putstr(tmpbuf); p = error_message(kerr); putstr(p); break; case 'm': /* %m => errno value (int) */ /* Like syslog's %m except the errno value is passed in rather than the current value. */ err = va_arg(args, int); putf("%d/", err); p = NULL; #ifdef HAVE_STRERROR_R if (strerror_r(err, tmpbuf, sizeof(tmpbuf)) == 0) p = tmpbuf; #endif if (p == NULL) p = strerror(err); putstr(p); break; case 'F': /* %F => fd_set *, fd_set *, fd_set *, int */ rfds = va_arg(args, fd_set *); wfds = va_arg(args, fd_set *); xfds = va_arg(args, fd_set *); maxfd = va_arg(args, int); for (i = 0; i < maxfd; i++) { int r = FD_ISSET(i, rfds); int w = wfds && FD_ISSET(i, wfds); int x = xfds && FD_ISSET(i, xfds); if (r || w || x) { putf(" %d", i); if (r) putstr("r"); if (w) putstr("w"); if (x) putstr("x"); } } putstr(" "); break; case 's': /* %s => char * */ p = va_arg(args, const char *); putstr(p); break; case 't': /* %t => struct timeval * */ tv = va_arg(args, struct timeval *); if (tv) { snprintf(tmpbuf, sizeof(tmpbuf), "%ld.%06ld", (long) tv->tv_sec, (long) tv->tv_usec); putstr(tmpbuf); } else putstr("never"); break; case 'd': /* %d => int */ putf("%d", va_arg(args, int)); break; case 'p': /* %p => pointer */ putf("%p", va_arg(args, void*)); break; case 'A': /* %A => addrinfo */ ai = va_arg(args, struct addrinfo *); krb5int_buf_init_dynamic(&buf); if (ai->ai_socktype == SOCK_DGRAM) krb5int_buf_add(&buf, "dgram"); else if (ai->ai_socktype == SOCK_STREAM) krb5int_buf_add(&buf, "stream"); else krb5int_buf_add_fmt(&buf, "socktype%d", ai->ai_socktype); if (0 != getnameinfo (ai->ai_addr, ai->ai_addrlen, addrbuf, sizeof (addrbuf), portbuf, sizeof (portbuf), NI_NUMERICHOST | NI_NUMERICSERV)) { if (ai->ai_addr->sa_family == AF_UNSPEC) krb5int_buf_add(&buf, " AF_UNSPEC"); else krb5int_buf_add_fmt(&buf, " af%d", ai->ai_addr->sa_family); } else krb5int_buf_add_fmt(&buf, " %s.%s", addrbuf, portbuf); if (krb5int_buf_data(&buf)) putstr(krb5int_buf_data(&buf)); krb5int_free_buf(&buf); break; case 'D': /* %D => krb5_data * */ d = va_arg(args, krb5_data *); /* may not be nul-terminated */ put(d->data, d->length); break; } } va_end(args); #endif }