summaryrefslogtreecommitdiffstats
path: root/ipa-client
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2014-11-17 15:19:57 -0500
committerSimo Sorce <simo@redhat.com>2014-11-20 10:52:13 -0500
commitb1a30bff04fe9763b8b270590ec37084fd19b4e0 (patch)
tree4e42782080c991d02e4c75a81ccec48228f013de /ipa-client
parentc6afc489a1c9d86fd593bd47c4a8dae6d9a008d2 (diff)
downloadfreeipa-b1a30bff04fe9763b8b270590ec37084fd19b4e0.tar.gz
freeipa-b1a30bff04fe9763b8b270590ec37084fd19b4e0.tar.xz
freeipa-b1a30bff04fe9763b8b270590ec37084fd19b4e0.zip
Use asn1c helpers to encode/decode the getkeytab control
Replaces manual encoding with automatically generated code. Fixes: https://fedorahosted.org/freeipa/ticket/4718 https://fedorahosted.org/freeipa/ticket/4728 Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com> Reviewed-By: Nathaniel McCallum <npmccallum@redhat.com>
Diffstat (limited to 'ipa-client')
-rw-r--r--ipa-client/Makefile.am4
-rw-r--r--ipa-client/configure.ac2
-rw-r--r--ipa-client/ipa-getkeytab.c246
3 files changed, 53 insertions, 199 deletions
diff --git a/ipa-client/Makefile.am b/ipa-client/Makefile.am
index 2df175e53..b9c7020f3 100644
--- a/ipa-client/Makefile.am
+++ b/ipa-client/Makefile.am
@@ -14,11 +14,13 @@ export AM_CFLAGS
KRB5_UTIL_DIR=../util
KRB5_UTIL_SRCS=$(KRB5_UTIL_DIR)/ipa_krb5.c
+ASN1_UTIL_DIR=../asn1
AM_CPPFLAGS = \
-I. \
-I$(srcdir) \
-I$(KRB5_UTIL_DIR) \
+ -I$(ASN1_UTIL_DIR) \
-DPREFIX=\""$(prefix)"\" \
-DBINDIR=\""$(bindir)"\" \
-DLIBDIR=\""$(libdir)"\" \
@@ -45,6 +47,7 @@ ipa_getkeytab_SOURCES = \
$(NULL)
ipa_getkeytab_LDADD = \
+ ../asn1/libipaasn1.la \
$(KRB5_LIBS) \
$(OPENLDAP_LIBS) \
$(SASL_LIBS) \
@@ -80,6 +83,7 @@ ipa_join_LDADD = \
$(NULL)
SUBDIRS = \
+ ../asn1 \
ipaclient \
ipa-install \
man \
diff --git a/ipa-client/configure.ac b/ipa-client/configure.ac
index 34625622d..78da8e6e4 100644
--- a/ipa-client/configure.ac
+++ b/ipa-client/configure.ac
@@ -8,6 +8,7 @@ AC_PROG_LIBTOOL
AC_CONFIG_SRCDIR([ipaclient/__init__.py])
AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_SUBDIRS([../asn1])
AM_INIT_AUTOMAKE([foreign])
@@ -205,6 +206,7 @@ dnl ---------------------------------------------------------------------------
AC_CONFIG_FILES([
Makefile
+ ../asn1/Makefile
ipaclient/Makefile
ipa-install/Makefile
man/Makefile
diff --git a/ipa-client/ipa-getkeytab.c b/ipa-client/ipa-getkeytab.c
index bb43c333d..15255d6a3 100644
--- a/ipa-client/ipa-getkeytab.c
+++ b/ipa-client/ipa-getkeytab.c
@@ -40,6 +40,7 @@
#include "config.h"
#include "ipa_krb5.h"
+#include "ipa_asn1.h"
#include "ipa-client-common.h"
static int ldap_sasl_interact(LDAP *ld, unsigned flags, void *priv_data, void *sit)
@@ -295,14 +296,15 @@ done:
return ret;
}
-static BerElement *get_control_data(LDAPControl **list, const char *repoid)
+static int find_control_data(LDAPControl **list, const char *repoid,
+ struct berval *data)
{
LDAPControl *control = NULL;
int i;
if (!list) {
fprintf(stderr, _("Missing reply control list!\n"));
- return NULL;
+ return LDAP_OPERATIONS_ERROR;
}
for (i = 0; list[i]; i++) {
@@ -312,10 +314,22 @@ static BerElement *get_control_data(LDAPControl **list, const char *repoid)
}
if (!control) {
fprintf(stderr, _("Missing reply control!\n"));
- return NULL;
+ return LDAP_OPERATIONS_ERROR;
}
- return ber_init(&control->ldctl_value);
+ *data = control->ldctl_value;
+ return LDAP_SUCCESS;
+}
+
+static BerElement *get_control_data(LDAPControl **list, const char *repoid)
+{
+ struct berval data;
+ int ret;
+
+ ret = find_control_data(list, repoid, &data);
+ if (ret != LDAP_SUCCESS) return NULL;
+
+ return ber_init(&data);
}
static int ldap_set_keytab(krb5_context krbctx,
@@ -435,124 +449,42 @@ error_out:
return -1;
}
-/* Format of getkeytab control
- *
- * KeytabGetRequest ::= CHOICE {
- * newkeys [0] Newkeys,
- * curkeys [1] CurrentKeys,
- * reply [2] Reply
- * }
- *
- * NewKeys ::= SEQUENCE {
- * serviceIdentity [0] OCTET STRING,
- * enctypes [1] SEQUENCE OF Int16
- * password [2] OCTET STRING OPTIONAL,
- * }
- *
- * CurrentKeys ::= SEQUENCE {
- * serviceIdentity [0] OCTET STRING,
- * }
- *
- * Reply ::= SEQUENCE {
- * new_kvno Int32
- * keys SEQUENCE OF KrbKey,
- * }
- *
- * KrbKey ::= SEQUENCE {
- * key [0] EncryptionKey,
- * salt [1] KrbSalt OPTIONAL,
- * s2kparams [2] OCTET STRING OPTIONAL,
- * }
- *
- * EncryptionKey ::= SEQUENCE {
- * keytype [0] Int32,
- * keyvalue [1] OCTET STRING
- * }
- *
- * KrbSalt ::= SEQUENCE {
- * type [0] Int32,
- * salt [1] OCTET STRING
- * }
- */
-
-#define GK_REQUEST_NEWKEYS (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 0)
-#define GK_REQUEST_CURKEYS (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 1)
-#define GKREQ_SVCNAME_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 1)
-#define GKREQ_ENCTYPES_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 1)
-#define GKREQ_PASSWORD_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 2)
-
+/* use asn1c generated code to fill up control */
static struct berval *create_getkeytab_control(const char *svc_princ, bool gen,
const char *password,
struct krb_key_salt *encsalts,
int num_encsalts)
{
- struct berval *bval = NULL;
- BerElement *be;
- ber_tag_t ctag;
- ber_int_t e;
- int ret, i;
-
- be = ber_alloc_t(LBER_USE_DER);
- if (!be) {
- return NULL;
- }
-
- if (gen) {
- ctag = GK_REQUEST_NEWKEYS;
- } else {
- ctag = GK_REQUEST_CURKEYS;
- }
-
- ret = ber_printf(be, "t{ts", ctag, GKREQ_SVCNAME_TAG, svc_princ);
- if (ret == -1) {
- ber_free(be, 1);
- goto done;
- }
+ struct berval *result = NULL;
+ void *buffer = NULL;
+ size_t buflen;
+ long ets[num_encsalts];
+ bool ret;
+ int i;
if (gen) {
- ret = ber_printf(be, "t{", GKREQ_ENCTYPES_TAG);
- if (ret == -1) {
- ber_free(be, 1);
- goto done;
- }
for (i = 0; i < num_encsalts; i++) {
- e = encsalts[i].enctype;
- ret = ber_printf(be, "i", e);
- if (ret == -1) {
- ber_free(be, 1);
- goto done;
- }
- }
- ret = ber_printf(be, "}");
- if (ret == -1) {
- ber_free(be, 1);
- goto done;
- }
-
- if (password) {
- ret = ber_printf(be, "ts", GKREQ_PASSWORD_TAG, password);
- if (ret == -1) {
- ber_free(be, 1);
- goto done;
- }
+ ets[i] = encsalts[i].enctype;
}
}
+ ret = ipaasn1_enc_getkt(gen, svc_princ,
+ password, ets, num_encsalts,
+ &buffer, &buflen);
+ if (!ret) goto done;
- ret = ber_printf(be, "}");
- if (ret == -1) {
- ber_free(be, 1);
- goto done;
- }
+ result = malloc(sizeof(struct berval));
+ if (!result) goto done;
- ret = ber_flatten(be, &bval);
- if (ret == -1) {
- ber_free(be, 1);
- goto done;
- }
+ result->bv_val = buffer;
+ result->bv_len = buflen;
done:
- ber_free(be, 1);
- return bval;
+ if (result == NULL) {
+ if (buffer) {
+ free(buffer);
+ }
+ }
+ return result;
}
#define GK_REPLY_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 2)
@@ -571,13 +503,8 @@ static int ldap_get_keytab(krb5_context krbctx, bool generate, char *password,
struct berval *control = NULL;
LDAP *ld = NULL;
LDAPControl **srvctrl = NULL;
- BerElement *ber = NULL;
- ber_tag_t rtag;
- ber_tag_t ctag;
- ber_len_t tlen;
- ber_int_t vno;
- ber_int_t tint;
- struct berval tbval;
+ struct berval data;
+ bool res;
int ret;
*err_msg = NULL;
@@ -609,98 +536,19 @@ static int ldap_get_keytab(krb5_context krbctx, bool generate, char *password,
goto done;
}
- ber = get_control_data(srvctrl, KEYTAB_GET_OID);
- if (!ber) {
- *err_msg = _("Failed to find or parse reply control!\n");
- ret = LDAP_OPERATIONS_ERROR;
- goto done;
- }
-
- rtag = ber_scanf(ber, "t{i{", &ctag, &vno);
- if (rtag == LBER_ERROR || ctag != GK_REPLY_TAG) {
- *err_msg = _("Failed to parse control head!\n");
- ret = LDAP_OPERATIONS_ERROR;
- goto done;
- }
-
- keys->nkeys = 0;
- keys->ksdata = NULL;
-
- rtag = ber_peek_tag(ber, &tlen);
- for (int i = 0; rtag == LBER_SEQUENCE; i++) {
- if ((i % 5) == 0) {
- struct krb_key_salt *ksdata;
- ksdata = realloc(keys->ksdata,
- (i + 5) * sizeof(struct krb_key_salt));
- if (!ksdata) {
- *err_msg = _("Out of memory!\n");
- ret = LDAP_OPERATIONS_ERROR;
- goto done;
- }
- keys->ksdata = ksdata;
- }
- memset(&keys->ksdata[i], 0, sizeof(struct krb_key_salt));
- keys->nkeys = i + 1;
-
- rtag = ber_scanf(ber, "{t{io}", &ctag, &tint, &tbval);
- if (rtag == LBER_ERROR || ctag != GKREP_KEY_TAG) {
- *err_msg = _("Failed to parse enctype in key data!\n");
- ret = LDAP_OPERATIONS_ERROR;
- goto done;
- }
- keys->ksdata[i].enctype = tint;
- keys->ksdata[i].key.enctype = tint;
- keys->ksdata[i].key.length = tbval.bv_len;
- keys->ksdata[i].key.contents = malloc(tbval.bv_len);
- if (!keys->ksdata[i].key.contents) {
- *err_msg = _("Out of memory!\n");
- ret = LDAP_OPERATIONS_ERROR;
- goto done;
- }
- memcpy(keys->ksdata[i].key.contents, tbval.bv_val, tbval.bv_len);
- ber_memfree(tbval.bv_val);
-
- rtag = ber_peek_tag(ber, &tlen);
- if (rtag == GKREP_SALT_TAG) {
- rtag = ber_scanf(ber, "t{io}", &ctag, &tint, &tbval);
- if (rtag == LBER_ERROR) {
- *err_msg = _("Failed to parse salt in key data!\n");
- ret = LDAP_OPERATIONS_ERROR;
- goto done;
- }
- keys->ksdata[i].salttype = tint;
- keys->ksdata[i].salt.length = tbval.bv_len;
- keys->ksdata[i].salt.data = malloc(tbval.bv_len);
- if (!keys->ksdata[i].salt.data) {
- *err_msg = _("Out of memory!\n");
- ret = LDAP_OPERATIONS_ERROR;
- goto done;
- }
- memcpy(keys->ksdata[i].salt.data, tbval.bv_val, tbval.bv_len);
- ber_memfree(tbval.bv_val);
- }
- rtag = ber_scanf(ber, "}");
- if (rtag == LBER_ERROR) {
- *err_msg = _("Failed to parse ending of key data!\n");
- ret = LDAP_OPERATIONS_ERROR;
- goto done;
- }
-
- rtag = ber_peek_tag(ber, &tlen);
- }
+ ret = find_control_data(srvctrl, KEYTAB_GET_OID, &data);
+ if (ret != LDAP_SUCCESS) goto done;
- rtag = ber_scanf(ber, "}}");
- if (rtag == LBER_ERROR) {
- *err_msg = _("Failed to parse ending of control!\n");
+ res = ipaasn1_dec_getktreply(data.bv_val, data.bv_len, kvno, keys);
+ if (!res) {
+ *err_msg = _("Failed to decode control reply!\n");
ret = LDAP_OPERATIONS_ERROR;
goto done;
}
- *kvno = vno;
ret = LDAP_SUCCESS;
done:
- if (ber) ber_free(ber, 1);
if (ld) ldap_unbind_ext(ld, NULL, NULL);
if (control) ber_bvfree(control);
free(es);