Пример #1
0
/* 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);
}
Пример #2
0
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;
}
Пример #3
0
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);
    }
}
Пример #4
0
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;
}
Пример #5
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;
}
Пример #6
0
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
}