Exemplo n.º 1
0
static int
send_and_recv_tcp(krb5_socket_t fd,
		  time_t tmout,
		  const krb5_data *req,
		  krb5_data *rep)
{
    unsigned char len[4];
    unsigned long rep_len;
    krb5_data len_data;

    _krb5_put_int(len, req->length, 4);
    if(net_write (fd, len, sizeof(len)) < 0)
	return -1;
    if(net_write (fd, req->data, req->length) < 0)
	return -1;
    if (recv_loop (fd, tmout, 0, 4, &len_data) < 0)
	return -1;
    if (len_data.length != 4) {
	krb5_data_free (&len_data);
	return -1;
    }
    _krb5_get_int(len_data.data, &rep_len, 4);
    krb5_data_free (&len_data);
    if (recv_loop (fd, tmout, 0, rep_len, rep) < 0)
	return -1;
    if(rep->length != rep_len) {
	krb5_data_free (rep);
	return -1;
    }
    return 0;
}
Exemplo n.º 2
0
static int
send_and_recv_http(krb5_socket_t fd,
		   time_t tmout,
		   const char *prefix,
		   const krb5_data *req,
		   krb5_data *rep)
{
    char *request = NULL;
    char *str;
    int ret;
    int len = base64_encode(req->data, req->length, &str);

    if(len < 0)
	return -1;
    ret = asprintf(&request, "GET %s%s HTTP/1.0\r\n\r\n", prefix, str);
    free(str);
    if (ret < 0 || request == NULL)
	return -1;
    ret = net_write (fd, request, strlen(request));
    free (request);
    if (ret < 0)
	return ret;
    ret = recv_loop(fd, tmout, 0, 0, rep);
    if(ret)
	return ret;
    {
	unsigned long rep_len;
	char *s, *p;

	s = realloc(rep->data, rep->length + 1);
	if (s == NULL) {
	    krb5_data_free (rep);
	    return -1;
	}
	s[rep->length] = 0;
	p = strstr(s, "\r\n\r\n");
	if(p == NULL) {
	    krb5_data_zero(rep);
	    free(s);
	    return -1;
	}
	p += 4;
	rep->data = s;
	rep->length -= p - s;
	if(rep->length < 4) { /* remove length */
	    krb5_data_zero(rep);
	    free(s);
	    return -1;
	}
	rep->length -= 4;
	_krb5_get_int(p, &rep_len, 4);
	if (rep_len != rep->length) {
	    krb5_data_zero(rep);
	    free(s);
	    return -1;
	}
	memmove(rep->data, p + 4, rep->length);
    }
    return 0;
}
Exemplo n.º 3
0
static int
ipv4_mask_boundary(krb5_context context, const krb5_address *inaddr,
		   unsigned long len, krb5_address *low, krb5_address *high)
{
    unsigned long ia;
    uint32_t l, h, m = 0xffffffff;

    if (len > 32) {
	krb5_set_error_message(context, KRB5_PROG_ATYPE_NOSUPP,
			       N_("IPv4 prefix too large (%ld)", "len"), len);
	return KRB5_PROG_ATYPE_NOSUPP;
    }
    m = m << (32 - len);

    _krb5_get_int(inaddr->address.data, &ia, inaddr->address.length);

    l = ia & m;
    h = l | ~m;

    low->addr_type = KRB5_ADDRESS_INET;
    if(krb5_data_alloc(&low->address, 4) != 0)
	return -1;
    _krb5_put_int(low->address.data, l, low->address.length);

    high->addr_type = KRB5_ADDRESS_INET;
    if(krb5_data_alloc(&high->address, 4) != 0) {
	krb5_free_address(context, low);
	return -1;
    }
    _krb5_put_int(high->address.data, h, high->address.length);

    return 0;
}
Exemplo n.º 4
0
ssize_t
do_read (int fd, void *buf, size_t sz, void *ivec)
{
    if (do_encrypt) {
#ifdef KRB5
        if(auth_method == AUTH_KRB5) {
	    krb5_error_code ret;
	    uint32_t len, outer_len;
	    int status;
	    krb5_data data;
	    void *edata;

	    ret = krb5_net_read (context, &fd, &len, 4);
	    if (ret <= 0)
		return ret;
	    len = ntohl(len);
	    if (len > sz)
		abort ();
	    /* ivec will be non null for protocol version 2 */
	    if(ivec != NULL)
		outer_len = krb5_get_wrapped_length (context, crypto, len + 4);
	    else
		outer_len = krb5_get_wrapped_length (context, crypto, len);
	    edata = malloc (outer_len);
	    if (edata == NULL)
		errx (1, "malloc: cannot allocate %u bytes", outer_len);
	    ret = krb5_net_read (context, &fd, edata, outer_len);
	    if (ret <= 0) {
		free(edata);
		return ret;
	    }

	    status = krb5_decrypt_ivec(context, crypto, key_usage,
				       edata, outer_len, &data, ivec);
	    free (edata);
	
	    if (status)
		krb5_err (context, 1, status, "decrypting data");
	    if(ivec != NULL) {
		unsigned long l;
		if(data.length < len + 4)
		    errx (1, "data received is too short");
		_krb5_get_int(data.data, &l, 4);
		if(l != len)
		    errx (1, "inconsistency in received data");
		memcpy (buf, (unsigned char *)data.data+4, len);
	    } else
		memcpy (buf, data.data, len);
	    krb5_data_free (&data);
	    return len;
	} else
#endif /* KRB5 */
	    abort ();
    } else
	return read (fd, buf, sz);
}
Exemplo n.º 5
0
static krb5_error_code
AES_SHA1_string_to_key(krb5_context context,
		       krb5_enctype enctype,
		       krb5_data password,
		       krb5_salt salt,
		       krb5_data opaque,
		       krb5_keyblock *key)
{
    krb5_error_code ret;
    uint32_t iter;
    struct _krb5_encryption_type *et;
    struct _krb5_key_data kd;

    if (opaque.length == 0)
	iter = _krb5_AES_SHA1_string_to_default_iterator;
    else if (opaque.length == 4) {
	unsigned long v;
	_krb5_get_int(opaque.data, &v, 4);
	iter = ((uint32_t)v);
    } else
	return KRB5_PROG_KEYTYPE_NOSUPP; /* XXX */

    et = _krb5_find_enctype(enctype);
    if (et == NULL)
	return KRB5_PROG_KEYTYPE_NOSUPP;

    kd.schedule = NULL;
    ALLOC(kd.key, 1);
    if (kd.key == NULL)
	return krb5_enomem(context);
    kd.key->keytype = enctype;
    ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
    if (ret) {
	krb5_set_error_message (context, ret, N_("malloc: out of memory", ""));
	return ret;
    }

    ret = PKCS5_PBKDF2_HMAC(password.data, password.length,
			    salt.saltvalue.data, salt.saltvalue.length,
			    iter,
			    EVP_sha1(),
			    et->keytype->size, kd.key->keyvalue.data);
    if (ret != 1) {
	_krb5_free_key_data(context, &kd, et);
	krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
			       "Error calculating s2k");
	return KRB5_PROG_KEYTYPE_NOSUPP;
    }

    ret = _krb5_derive_key(context, et, &kd, "kerberos", strlen("kerberos"));
    if (ret == 0)
	ret = krb5_copy_keyblock_contents(context, kd.key, key);
    _krb5_free_key_data(context, &kd, et);

    return ret;
}
Exemplo n.º 6
0
static int
addrport_print_addr (const krb5_address *addr, char *str, size_t len)
{
    krb5_error_code ret;
    krb5_address addr1, addr2;
    uint16_t port = 0;
    size_t ret_len = 0, l, size = 0;
    krb5_storage *sp;

    sp = krb5_storage_from_data((krb5_data*)rk_UNCONST(&addr->address));
    if (sp == NULL)
        return ENOMEM;

    /* for totally obscure reasons, these are not in network byteorder */
    krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_LE);

    krb5_storage_seek(sp, 2, SEEK_CUR); /* skip first two bytes */
    krb5_ret_address(sp, &addr1);

    krb5_storage_seek(sp, 2, SEEK_CUR); /* skip two bytes */
    krb5_ret_address(sp, &addr2);
    krb5_storage_free(sp);
    if(addr2.addr_type == KRB5_ADDRESS_IPPORT && addr2.address.length == 2) {
	unsigned long value;
	_krb5_get_int(addr2.address.data, &value, 2);
	port = value;
    }
    l = strlcpy(str, "ADDRPORT:", len);
    ret_len += l;
    if (len > l)
	size += l;
    else
	size = len;

    ret = krb5_print_address(&addr1, str + size, len - size, &l);
    if (ret)
	return ret;
    ret_len += l;
    if (len - size > l)
	size += l;
    else
	size = len;

    ret = snprintf(str + size, len - size, ",PORT=%u", port);
    if (ret < 0)
	return EINVAL;
    ret_len += ret;
    return ret_len;
}
Exemplo n.º 7
0
Arquivo: store.c Projeto: gojdic/samba
static krb5_error_code
krb5_ret_int(krb5_storage *sp,
	     int32_t *value,
	     size_t len)
{
    int ret;
    unsigned char v[4];
    unsigned long w;
    ret = sp->fetch(sp, v, len);
    if(ret != len)
	return (ret<0)?errno:sp->eof_code;
    _krb5_get_int(v, &w, len);
    *value = w;
    return 0;
}
Exemplo n.º 8
0
krb5_error_code
kadmind_loop(krb5_context context,
	     krb5_keytab keytab,
	     krb5_socket_t sock)
{
    u_char buf[sizeof(KRB5_SENDAUTH_VERSION) + 4];
    ssize_t n;
    unsigned long len;

    n = krb5_net_read(context, &sock, buf, 4);
    if(n == 0)
	exit(0);
    if(n < 0)
	krb5_err(context, 1, errno, "read");
    _krb5_get_int(buf, &len, 4);

    if (len == sizeof(KRB5_SENDAUTH_VERSION)) {

	n = krb5_net_read(context, &sock, buf + 4, len);
	if (n < 0)
	    krb5_err (context, 1, errno, "reading sendauth version");
	if (n == 0)
	    krb5_errx (context, 1, "EOF reading sendauth version");

	if(memcmp(buf + 4, KRB5_SENDAUTH_VERSION, len) == 0) {
	    handle_v5(context, keytab, sock);
	    return 0;
	}
	len += 4;
    } else
	len = 4;

    handle_mit(context, buf, len, sock);

    return 0;
}
Exemplo n.º 9
0
static krb5_error_code
process_reply (krb5_context context,
	       krb5_auth_context auth_context,
	       int is_stream,
	       int sock,
	       int *result_code,
	       krb5_data *result_code_string,
	       krb5_data *result_string,
	       const char *host)
{
    krb5_error_code ret;
    u_char reply[1024 * 3];
    ssize_t len;
    u_int16_t pkt_len, pkt_ver;
    krb5_data ap_rep_data;
    int save_errno;

    len = 0;
    if (is_stream) {
	while (len < sizeof(reply)) {
	    unsigned long size;

	    ret = recvfrom (sock, reply + len, sizeof(reply) - len, 
			    0, NULL, NULL);
	    if (ret < 0) {
		save_errno = errno;
		krb5_set_error_string(context, "recvfrom %s: %s",
				      host, strerror(save_errno));
		return save_errno;
	    } else if (ret == 0) {
		krb5_set_error_string(context, "recvfrom timeout %s", host);
		return 1;
	    }
	    len += ret;
	    if (len < 4)
		continue;
	    _krb5_get_int(reply, &size, 4);
	    if (size + 4 < len)
		continue;
	    memmove(reply, reply + 4, size);		
	    len = size;
	    break;
	}
	if (len == sizeof(reply)) {
	    krb5_set_error_string(context, "message too large from %s",
				  host);
	    return ENOMEM;
	}
    } else {
	ret = recvfrom (sock, reply, sizeof(reply), 0, NULL, NULL);
	if (ret < 0) {
	    save_errno = errno;
	    krb5_set_error_string(context, "recvfrom %s: %s",
				  host, strerror(save_errno));
	    return save_errno;
	}
	len = ret;
    }

    if (len < 6) {
	str2data (result_string, "server %s sent to too short message "
		  "(%ld bytes)", host, (long)len);
	*result_code = KRB5_KPASSWD_MALFORMED;
	return 0;
    }

    pkt_len = (reply[0] << 8) | (reply[1]);
    pkt_ver = (reply[2] << 8) | (reply[3]);

    if ((pkt_len != len) || (reply[1] == 0x7e || reply[1] == 0x5e)) {
	KRB_ERROR error;
	size_t size;
	u_char *p;

	memset(&error, 0, sizeof(error));

	ret = decode_KRB_ERROR(reply, len, &error, &size);
	if (ret)
	    return ret;

	if (error.e_data->length < 2) {
	    str2data(result_string, "server %s sent too short "
		     "e_data to print anything usable", host);
	    free_KRB_ERROR(&error);
	    *result_code = KRB5_KPASSWD_MALFORMED;
	    return 0;
	}

	p = error.e_data->data;
	*result_code = (p[0] << 8) | p[1];
	if (error.e_data->length == 2)
	    str2data(result_string, "server only sent error code");
	else 
	    krb5_data_copy (result_string,
			    p + 2,
			    error.e_data->length - 2);
	free_KRB_ERROR(&error);
	return 0;
    }

    if (pkt_len != len) {
	str2data (result_string, "client: wrong len in reply");
	*result_code = KRB5_KPASSWD_MALFORMED;
	return 0;
    }
    if (pkt_ver != KRB5_KPASSWD_VERS_CHANGEPW) {
	str2data (result_string,
		  "client: wrong version number (%d)", pkt_ver);
	*result_code = KRB5_KPASSWD_MALFORMED;
	return 0;
    }

    ap_rep_data.data = reply + 6;
    ap_rep_data.length  = (reply[4] << 8) | (reply[5]);
  
    if (reply + len < (u_char *)ap_rep_data.data + ap_rep_data.length) {
	str2data (result_string, "client: wrong AP len in reply");
	*result_code = KRB5_KPASSWD_MALFORMED;
	return 0;
    }

    if (ap_rep_data.length) {
	krb5_ap_rep_enc_part *ap_rep;
	krb5_data priv_data;
	u_char *p;

	priv_data.data   = (u_char*)ap_rep_data.data + ap_rep_data.length;
	priv_data.length = len - ap_rep_data.length - 6;

	ret = krb5_rd_rep (context,
			   auth_context,
			   &ap_rep_data,
			   &ap_rep);
	if (ret)
	    return ret;

	krb5_free_ap_rep_enc_part (context, ap_rep);

	ret = krb5_rd_priv (context,
			    auth_context,
			    &priv_data,
			    result_code_string,
			    NULL);
	if (ret) {
	    krb5_data_free (result_code_string);
	    return ret;
	}

	if (result_code_string->length < 2) {
	    *result_code = KRB5_KPASSWD_MALFORMED;
	    str2data (result_string,
		      "client: bad length in result");
	    return 0;
	}

        p = result_code_string->data;
      
        *result_code = (p[0] << 8) | p[1];
        krb5_data_copy (result_string,
                        (unsigned char*)result_code_string->data + 2,
                        result_code_string->length - 2);
        return 0;
    } else {
	KRB_ERROR error;
	size_t size;
	u_char *p;
      
	ret = decode_KRB_ERROR(reply + 6, len - 6, &error, &size);
	if (ret) {
	    return ret;
	}
	if (error.e_data->length < 2) {
	    krb5_warnx (context, "too short e_data to print anything usable");
	    return 1;		/* XXX */
	}

	p = error.e_data->data;
	*result_code = (p[0] << 8) | p[1];
	krb5_data_copy (result_string,
			p + 2,
			error.e_data->length - 2);
	return 0;
    }
}
Exemplo n.º 10
0
static krb5_error_code
AES_SHA2_string_to_key(krb5_context context,
		       krb5_enctype enctype,
		       krb5_data password,
		       krb5_salt salt,
		       krb5_data opaque,
		       krb5_keyblock *key)
{
    krb5_error_code ret;
    uint32_t iter;
    struct _krb5_encryption_type *et = NULL;
    struct _krb5_key_data kd;
    krb5_data saltp;
    size_t enctypesz;
    const EVP_MD *md = NULL;

    krb5_data_zero(&saltp);
    kd.key = NULL;
    kd.schedule = NULL;

    if (opaque.length == 0) {
	iter = _krb5_AES_SHA2_string_to_default_iterator;
    } else if (opaque.length == 4) {
	unsigned long v;
	_krb5_get_int(opaque.data, &v, 4);
	iter = ((uint32_t)v);
    } else {
	ret = KRB5_PROG_KEYTYPE_NOSUPP; /* XXX */
	goto cleanup;
    }

    et = _krb5_find_enctype(enctype);
    if (et == NULL) {
	ret = KRB5_PROG_KEYTYPE_NOSUPP;
	goto cleanup;
    }

    kd.schedule = NULL;
    ALLOC(kd.key, 1);
    if (kd.key == NULL) {
	ret = krb5_enomem(context);
	goto cleanup;
    }
    kd.key->keytype = enctype;
    ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
    if (ret) {
	ret = krb5_enomem(context);
	goto cleanup;
    }

    enctypesz = strlen(et->name) + 1;
    ret = krb5_data_alloc(&saltp, enctypesz + salt.saltvalue.length);
    if (ret) {
	ret = krb5_enomem(context);
	goto cleanup;
    }
    memcpy(saltp.data, et->name, enctypesz);
    memcpy((unsigned char *)saltp.data + enctypesz,
	   salt.saltvalue.data, salt.saltvalue.length);

    ret = _krb5_aes_sha2_md_for_enctype(context, enctype, &md);
    if (ret)
	goto cleanup;

    ret = PKCS5_PBKDF2_HMAC(password.data, password.length,
			    saltp.data, saltp.length,
			    iter, md,
			    et->keytype->size, kd.key->keyvalue.data);
    if (ret != 1) {
	krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
			       "Error calculating s2k");
	ret = KRB5_PROG_KEYTYPE_NOSUPP;
	goto cleanup;
    }

    ret = _krb5_derive_key(context, et, &kd, "kerberos", strlen("kerberos"));
    if (ret)
	goto cleanup;

    ret = krb5_copy_keyblock_contents(context, kd.key, key);
    if (ret)
	goto cleanup;

cleanup:
    krb5_data_free(&saltp);
    _krb5_free_key_data(context, &kd, et);

    return ret;
}