Ejemplo n.º 1
0
/*
 * Write a field of bytes from krb5_data as a hexadecimal string.  Write empty
 * strings as "-1" unless requested.
 */
static int
write_data(struct rec_args *args, krb5_data *data)
{
    int ret;
    char *p;
    size_t i;
    struct k5buf buf;
    struct rechandle *h = args->rh;
    struct tdopts *opts = args->opts;

    if (data->length == 0 && !opts->emptyhex_empty) {
        if (writefield(h, "-1") < 0)
            return -1;
        return 0;
    }
    k5_buf_init_dynamic(&buf);
    p = data->data;
    for (i = 0; i < data->length; i++)
        k5_buf_add_fmt(&buf, "%02x", (unsigned char)p[i]);

    if (buf.data == NULL) {
        errno = ENOMEM;
        return -1;
    }
    ret = writefield(h, "%s", (char *)buf.data);
    k5_buf_free(&buf);
    return ret;
}
Ejemplo n.º 2
0
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 {
        k5_buf_init_dynamic(&buf);
        for (p = i_princ_name; p < at_rlm_name; p++) {
            if (*p == '@')
                k5_buf_add(&buf, "\\");
            k5_buf_add_len(&buf, p, 1);
        }
        k5_buf_add(&buf, at_rlm_name);
        *o_princ_name = k5_buf_data(&buf);
        if (!*o_princ_name)
            return ENOMEM;
    }
    return 0;
}
Ejemplo n.º 3
0
Archivo: k5buf.c Proyecto: PADL/krb5
void
k5_buf_init_dynamic_zap(struct k5buf *buf)
{
    k5_buf_init_dynamic(buf);
    if (buf->buftype == K5BUF_DYNAMIC)
        buf->buftype = K5BUF_DYNAMIC_ZAP;
}
Ejemplo n.º 4
0
static krb5_error_code
read_principal(krb5_context context, krb5_ccache id, krb5_principal *princ)
{
    krb5_error_code ret;
    struct k5buf buf;
    size_t maxsize;
    unsigned char *bytes;

    *princ = NULL;
    k5_cc_mutex_assert_locked(context, &((fcc_data *)id->data)->lock);
    k5_buf_init_dynamic(&buf);

    /* Read the principal representation into memory. */
    ret = get_size(context, id, &maxsize);
    if (ret)
        goto cleanup;
    ret = load_principal(context, id, maxsize, &buf);
    if (ret)
        goto cleanup;
    bytes = (unsigned char *)k5_buf_data(&buf);
    if (bytes == NULL) {
        ret = ENOMEM;
        goto cleanup;
    }

    /* Unmarshal it from buf into princ. */
    ret = k5_unmarshal_princ(bytes, k5_buf_len(&buf), version(id), princ);

cleanup:
    k5_free_buf(&buf);
    return ret;
}
Ejemplo n.º 5
0
static krb5_error_code
make_proxy_request(struct conn_state *state, const krb5_data *realm,
                   const krb5_data *message, char **req_out, size_t *len_out)
{
    krb5_kkdcp_message pm;
    krb5_data *encoded_pm = NULL;
    struct k5buf buf;
    const char *uri_path;
    krb5_error_code ret;

    *req_out = NULL;
    *len_out = 0;

    /*
     * Stuff the message length in at the front of the kerb_message field
     * before encoding.  The proxied messages are actually the payload we'd
     * be sending and receiving if we were using plain TCP.
     */
    memset(&pm, 0, sizeof(pm));
    ret = alloc_data(&pm.kerb_message, message->length + 4);
    if (ret != 0)
        goto cleanup;
    store_32_be(message->length, pm.kerb_message.data);
    memcpy(pm.kerb_message.data + 4, message->data, message->length);
    pm.target_domain = *realm;
    ret = encode_krb5_kkdcp_message(&pm, &encoded_pm);
    if (ret != 0)
        goto cleanup;

    /* Build the request to transmit: the headers + the proxy message. */
    k5_buf_init_dynamic(&buf);
    uri_path = (state->http.uri_path != NULL) ? state->http.uri_path : "";
    k5_buf_add_fmt(&buf, "POST /%s HTTP/1.0\r\n", uri_path);
    k5_buf_add(&buf, "Cache-Control: no-cache\r\n");
    k5_buf_add(&buf, "Pragma: no-cache\r\n");
    k5_buf_add(&buf, "User-Agent: kerberos/1.0\r\n");
    k5_buf_add(&buf, "Content-type: application/kerberos\r\n");
    k5_buf_add_fmt(&buf, "Content-Length: %d\r\n\r\n", encoded_pm->length);
    k5_buf_add_len(&buf, encoded_pm->data, encoded_pm->length);
    if (k5_buf_status(&buf) != 0) {
        ret = ENOMEM;
        goto cleanup;
    }

    *req_out = buf.data;
    *len_out = buf.len;

cleanup:
    krb5_free_data_contents(NULL, &pm.kerb_message);
    krb5_free_data(NULL, encoded_pm);
    return ret;
}
Ejemplo n.º 6
0
Archivo: auth_acl.c Proyecto: PADL/krb5
/*
 * Get a line from the ACL file.  Lines ending with \ are continued on the next
 * line.  The caller should set *lineno to 1 and *incr to 0 before the first
 * call.  On successful return, *lineno will be the line number of the line
 * read.  Return a pointer to the line on success, or NULL on end of file or
 * read failure.
 */
static char *
get_line(FILE *fp, const char *fname, int *lineno, int *incr)
{
    const int chunksize = 128;
    struct k5buf buf;
    size_t old_len;
    char *p;

    /* Increment *lineno by the number of newlines from the last line. */
    *lineno += *incr;
    *incr = 0;

    k5_buf_init_dynamic(&buf);
    for (;;) {
        /* Read at least part of a line into the buffer. */
        old_len = buf.len;
        p = k5_buf_get_space(&buf, chunksize);
        if (p == NULL)
            return NULL;

        if (fgets(p, chunksize, fp) == NULL) {
            /* We reached the end.  Return a final unterminated line, if there
             * is one and it's not a comment. */
            k5_buf_truncate(&buf, old_len);
            if (buf.len > 0 && *(char *)buf.data != '#')
                return buf.data;
            k5_buf_free(&buf);
            return NULL;
        }

        /* Set the buffer length based on the actual amount read. */
        k5_buf_truncate(&buf, old_len + strlen(p));

        p = buf.data;
        if (buf.len > 0 && p[buf.len - 1] == '\n') {
            /* We have a complete raw line in the buffer. */
            (*incr)++;
            k5_buf_truncate(&buf, buf.len - 1);
            if (buf.len > 0 && p[buf.len - 1] == '\\') {
                /* This line has a continuation marker; keep reading. */
                k5_buf_truncate(&buf, buf.len - 1);
            } else if (buf.len == 0 || *p == '#') {
                /* This line is empty or a comment.  Start over. */
                *lineno += *incr;
                *incr = 0;
                k5_buf_truncate(&buf, 0);
            } else {
                return buf.data;
            }
        }
    }
}
Ejemplo n.º 7
0
/*
 * Double any quote characters present in a quoted field.
 */
static char *
qquote(struct flavor *fl, const char *s)
{
    const char *sp;
    struct k5buf buf;

    k5_buf_init_dynamic(&buf);
    for (sp = s; *sp != '\0'; sp++) {
        k5_buf_add_len(&buf, sp, 1);
        if (*sp == fl->quotechar)
            k5_buf_add_len(&buf, sp, 1);
    }
    return buf.data;
}
Ejemplo n.º 8
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;

    k5_buf_init_dynamic(&buf);
    while (TRUE) {
        count = strcspn(in, special);
        k5_buf_add_len(&buf, in, count);
        in += count;
        if (*in == '\0')
            break;
        k5_buf_add_fmt(&buf, "\\%2x", (unsigned char)*in++);
    }
    return buf.data;
}
Ejemplo n.º 9
0
/* Get the next credential from the cache file. */
static krb5_error_code KRB5_CALLCONV
fcc_next_cred(krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor,
              krb5_creds *creds)
{
    krb5_error_code ret;
    krb5_fcc_cursor *fcursor = *cursor;
    fcc_data *data = id->data;
    struct k5buf buf;
    size_t maxsize;
    unsigned char *bytes;

    memset(creds, 0, sizeof(*creds));
    k5_cc_mutex_lock(context, &data->lock);
    MAYBE_OPEN(context, id, FCC_OPEN_RDONLY);
    k5_buf_init_dynamic(&buf);

    if (fcc_lseek(data, fcursor->pos, SEEK_SET) == -1) {
        ret = interpret_errno(context, errno);
        goto cleanup;
    }

    /* Load a marshalled cred into memory. */
    ret = get_size(context, id, &maxsize);
    if (ret)
        return ret;
    ret = load_cred(context, id, maxsize, &buf);
    if (ret)
        goto cleanup;
    bytes = (unsigned char *)k5_buf_data(&buf);
    if (bytes == NULL) {
        ret = ENOMEM;
        goto cleanup;
    }

    /* Unmarshal it from buf into creds. */
    fcursor->pos = fcc_lseek(data, 0, SEEK_CUR);
    ret = k5_unmarshal_cred(bytes, k5_buf_len(&buf), version(id), creds);

cleanup:
    k5_free_buf(&buf);
    MAYBE_CLOSE(context, id, ret);
    k5_cc_mutex_unlock(context, &data->lock);
    return ret;
}
Ejemplo n.º 10
0
static char *
trace_format(krb5_context context, const char *fmt, va_list ap)
{
    struct k5buf buf;
    krb5_error_code kerr;
    size_t len, i;
    int err;
    struct conn_state *cs;
    const krb5_data *d;
    krb5_data data;
    char addrbuf[NI_MAXHOST], portbuf[NI_MAXSERV], tmpbuf[200], *str;
    const char *p;
    krb5_const_principal princ;
    const krb5_keyblock *keyblock;
    krb5_key key;
    const krb5_checksum *cksum;
    krb5_pa_data **padata;
    krb5_ccache ccache;
    krb5_keytab keytab;
    krb5_creds *creds;
    krb5_enctype *etypes, etype;

    k5_buf_init_dynamic(&buf);
    while (TRUE) {
        /* Advance to the next word in braces. */
        len = strcspn(fmt, "{");
        k5_buf_add_len(&buf, fmt, len);
        if (fmt[len] == '\0')
            break;
        fmt += len + 1;
        len = strcspn(fmt, "}");
        if (fmt[len] == '\0' || len > sizeof(tmpbuf) - 1)
            break;
        memcpy(tmpbuf, fmt, len);
        tmpbuf[len] = '\0';
        fmt += len + 1;

        /* Process the format word. */
        if (strcmp(tmpbuf, "int") == 0) {
            k5_buf_add_fmt(&buf, "%d", va_arg(ap, int));
        } else if (strcmp(tmpbuf, "long") == 0) {
Ejemplo n.º 11
0
/*
 * Expand tokens in path_in to produce *path_out.  Arguments after path_out are
 * pairs of extra token names and replacement values, terminated by a NULL.
 * The caller should free *path_out with free().
 */
krb5_error_code
k5_expand_path_tokens_extra(krb5_context context, const char *path_in,
                            char **path_out, ...)
{
    krb5_error_code ret;
    struct k5buf buf;
    char *tok_begin, *tok_end, *tok_val, **extra_tokens = NULL;
    const char *path_left;
    size_t nargs = 0, i;
    va_list ap;

    *path_out = NULL;

    k5_buf_init_dynamic(&buf);

    /* Count extra tokens. */
    va_start(ap, path_out);
    while (va_arg(ap, const char *) != NULL)
        nargs++;
    va_end(ap);
    if (nargs % 2 != 0)
        return EINVAL;

    /* Get extra tokens. */
    if (nargs > 0) {
        extra_tokens = k5calloc(nargs + 1, sizeof(char *), &ret);
        if (extra_tokens == NULL)
            goto cleanup;
        va_start(ap, path_out);
        for (i = 0; i < nargs; i++) {
            extra_tokens[i] = strdup(va_arg(ap, const char *));
            if (extra_tokens[i] == NULL) {
                ret = ENOMEM;
                va_end(ap);
                goto cleanup;
            }
        }
        va_end(ap);
    }
Ejemplo n.º 12
0
/* Get any auth indicator values from LDAP and update the "require_auth"
 * string. */
static krb5_error_code
get_ldap_auth_ind(krb5_context context, LDAP *ld, LDAPMessage *ldap_ent,
                  krb5_db_entry *entry, unsigned int *mask)
{
    krb5_error_code ret;
    int i;
    char **auth_inds = NULL;
    struct k5buf buf = EMPTY_K5BUF;

    auth_inds = ldap_get_values(ld, ldap_ent, "krbPrincipalAuthInd");
    if (auth_inds == NULL)
        return 0;

    k5_buf_init_dynamic(&buf);

    /* Make a space seperated list of indicators. */
    for (i = 0; auth_inds[i] != NULL; i++) {
        k5_buf_add(&buf, auth_inds[i]);
        if (auth_inds[i + 1] != NULL)
            k5_buf_add(&buf, " ");
    }

    ret = k5_buf_status(&buf);
    if (ret)
        goto cleanup;

    ret = krb5_dbe_set_string(context, entry, KRB5_KDB_SK_REQUIRE_AUTH,
                              buf.data);
    if (!ret)
        *mask |= KDB_AUTH_IND_ATTR;

cleanup:
    k5_buf_free(&buf);
    ldap_value_free(auth_inds);
    return ret;
}
Ejemplo n.º 13
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 *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. */
        k5_buf_init_dynamic(&extbuf);
        k5_buf_add_fmt(&extbuf, "HASH:%s %lu:%s %lu:%s", rep->msghash,
                       (unsigned long)clientlen, rep->client,
                       (unsigned long)serverlen, rep->server);
        if (k5_buf_status(&extbuf) != 0)
            return KRB5_RC_MALLOC;
        extstr = extbuf.data;

        /*
         * Put the extension value into the server field of a
         * regular-format record, with an empty client field.
         */
        k5_buf_init_dynamic(&buf);
        len = 1;
        k5_buf_add_len(&buf, (char *)&len, sizeof(len));
        k5_buf_add_len(&buf, "", 1);
        len = strlen(extstr) + 1;
        k5_buf_add_len(&buf, (char *)&len, sizeof(len));
        k5_buf_add_len(&buf, extstr, len);
        k5_buf_add_len(&buf, (char *)&rep->cusec, sizeof(rep->cusec));
        k5_buf_add_len(&buf, (char *)&rep->ctime, sizeof(rep->ctime));
        free(extstr);
    } else  /* No extension record needed. */
        k5_buf_init_dynamic(&buf);

    len = clientlen + 1;
    k5_buf_add_len(&buf, (char *)&len, sizeof(len));
    k5_buf_add_len(&buf, rep->client, len);
    len = serverlen + 1;
    k5_buf_add_len(&buf, (char *)&len, sizeof(len));
    k5_buf_add_len(&buf, rep->server, len);
    k5_buf_add_len(&buf, (char *)&rep->cusec, sizeof(rep->cusec));
    k5_buf_add_len(&buf, (char *)&rep->ctime, sizeof(rep->ctime));

    if (k5_buf_status(&buf) != 0)
        return KRB5_RC_MALLOC;

    ret = krb5_rc_io_write(context, &t->d, buf.data, buf.len);
    k5_buf_free(&buf);
    return ret;
}
Ejemplo n.º 14
0
Archivo: chpw.c Proyecto: Akasurde/krb5
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;
    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);

    k5_buf_init_dynamic(&buf);

    /*
     * Update src/tests/misc/test_chpw_message.c if changing these strings!
     */

    if (policy.password_properties & AD_POLICY_COMPLEX) {
        k5_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);
        k5_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);
        k5_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);
        k5_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);
    }

    if (k5_buf_status(&buf) != 0)
        return ENOMEM;

    if (buf.len > 0)
        *msg_out = buf.data;
    else
        k5_buf_free(&buf);
    return 0;
}