/* Return a copy of in, quoting all characters which are special in an LDAP * filter (RFC 4515) or DN string (RFC 4514). Return NULL on failure. */ char * ldap_filter_correct (char *in) { size_t count; const char special[] = "*()\\ #\"+,;<>"; struct k5buf buf; krb5int_buf_init_dynamic(&buf); while (TRUE) { count = strcspn(in, special); krb5int_buf_add_len(&buf, in, count); in += count; if (*in == '\0') break; krb5int_buf_add_fmt(&buf, "\\%2x", (unsigned char)*in++); } return krb5int_buf_data(&buf); }
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; }
static krb5_error_code krb5_rc_io_store(krb5_context context, struct dfl_data *t, krb5_donot_replay *rep) { size_t clientlen, serverlen; unsigned int len; krb5_error_code ret; struct k5buf buf, extbuf; char *ptr, *extstr; clientlen = strlen(rep->client); serverlen = strlen(rep->server); if (rep->msghash) { /* * Write a hash extension record, to be followed by a record * in regular format (without the message hash) for the * benefit of old implementations. */ /* Format the extension value so we know its length. */ krb5int_buf_init_dynamic(&extbuf); krb5int_buf_add_fmt(&extbuf, "HASH:%s %lu:%s %lu:%s", rep->msghash, (unsigned long) clientlen, rep->client, (unsigned long) serverlen, rep->server); extstr = krb5int_buf_data(&extbuf); if (!extstr) return KRB5_RC_MALLOC; /* * Put the extension value into the server field of a * regular-format record, with an empty client field. */ krb5int_buf_init_dynamic(&buf); len = 1; krb5int_buf_add_len(&buf, (char *) &len, sizeof(len)); krb5int_buf_add_len(&buf, "", 1); len = strlen(extstr) + 1; krb5int_buf_add_len(&buf, (char *) &len, sizeof(len)); krb5int_buf_add_len(&buf, extstr, len); krb5int_buf_add_len(&buf, (char *) &rep->cusec, sizeof(rep->cusec)); krb5int_buf_add_len(&buf, (char *) &rep->ctime, sizeof(rep->ctime)); free(extstr); } else /* No extension record needed. */ krb5int_buf_init_dynamic(&buf); len = clientlen + 1; krb5int_buf_add_len(&buf, (char *) &len, sizeof(len)); krb5int_buf_add_len(&buf, rep->client, len); len = serverlen + 1; krb5int_buf_add_len(&buf, (char *) &len, sizeof(len)); krb5int_buf_add_len(&buf, rep->server, len); krb5int_buf_add_len(&buf, (char *) &rep->cusec, sizeof(rep->cusec)); krb5int_buf_add_len(&buf, (char *) &rep->ctime, sizeof(rep->ctime)); ptr = krb5int_buf_data(&buf); if (ptr == NULL) return KRB5_RC_MALLOC; ret = krb5_rc_io_write(context, &t->d, ptr, krb5int_buf_len(&buf)); krb5int_free_buf(&buf); return ret; }
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 }