From 55172f11776453c0f8defb1363dd144b29f181d3 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 17 Nov 2014 15:19:57 -0500 Subject: [PATCH] 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 Reviewed-By: Nathaniel McCallum --- Makefile | 1 + daemons/configure.ac | 2 + .../ipa-slapi-plugins/ipa-pwd-extop/Makefile.am | 7 +- .../ipa-pwd-extop/ipa_pwd_extop.c | 241 ++++---------------- ipa-client/Makefile.am | 4 + ipa-client/configure.ac | 2 + ipa-client/ipa-getkeytab.c | 246 ++++----------------- 7 files changed, 107 insertions(+), 396 deletions(-) diff --git a/Makefile b/Makefile index c1a298f91717246e8dab5e3f0de47d0ac9b2ae35..8fd0c60e392d720f47c8ee7c4b674727dc5eb789 100644 --- a/Makefile +++ b/Makefile @@ -75,6 +75,7 @@ client: client-autogen bootstrap-autogen: version-update client-autogen @echo "Building IPA $(IPA_VERSION)" + cd asn1; if [ ! -e Makefile ]; then ../autogen.sh --prefix=/usr --sysconfdir=/etc --localstatedir=/var --libdir=$(LIBDIR); fi cd daemons; if [ ! -e Makefile ]; then ../autogen.sh --prefix=/usr --sysconfdir=/etc --localstatedir=/var --libdir=$(LIBDIR) --with-openldap; fi cd install; if [ ! -e Makefile ]; then ../autogen.sh --prefix=/usr --sysconfdir=/etc --localstatedir=/var --libdir=$(LIBDIR); fi diff --git a/daemons/configure.ac b/daemons/configure.ac index bfcdeadcd1dc73762d8c773ee50210d9bdb91e92..e81aa60e381e035aff73bf27475fc0f101a5fbf9 100644 --- a/daemons/configure.ac +++ b/daemons/configure.ac @@ -5,6 +5,7 @@ AC_INIT([ipa-server], [https://hosted.fedoraproject.org/projects/freeipa/newticket]) AC_CONFIG_HEADERS([config.h]) +AC_CONFIG_SUBDIRS([../asn1]) AM_INIT_AUTOMAKE([foreign]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES]) @@ -305,6 +306,7 @@ AC_SUBST(LDFLAGS) AC_CONFIG_FILES([ Makefile + ../asn1/Makefile ipa-kdb/Makefile ipa-sam/Makefile ipa-otpd/Makefile diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am b/daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am index 4cf80ec802b40bb579a44fc9357c6a8119dab577..77beca2da0810ed5507d95b21f99d22f63b05fc1 100644 --- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am +++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am @@ -6,6 +6,7 @@ KRB5_UTIL_DIR = ../../../util KRB5_UTIL_SRCS = $(KRB5_UTIL_DIR)/ipa_krb5.c \ $(KRB5_UTIL_DIR)/ipa_pwd.c \ $(KRB5_UTIL_DIR)/ipa_pwd_ntlm.c +ASN1_UTIL_DIR=../../../asn1 AM_CPPFLAGS = \ -I. \ @@ -13,6 +14,7 @@ AM_CPPFLAGS = \ -I$(srcdir)/../libotp \ -I$(PLUGIN_COMMON_DIR) \ -I$(KRB5_UTIL_DIR) \ + -I$(ASN1_UTIL_DIR) \ -I$(COMMON_BER_DIR) \ -DPREFIX=\""$(prefix)"\" \ -DBINDIR=\""$(bindir)"\" \ @@ -38,7 +40,10 @@ AM_LDFLAGS = \ # Plugin Binary plugindir = $(libdir)/dirsrv/plugins plugin_LTLIBRARIES = libipa_pwd_extop.la -libipa_pwd_extop_la_LIBADD = $(builddir)/../libotp/libotp.la +libipa_pwd_extop_la_LIBADD = \ + $(builddir)/../libotp/libotp.la \ + $(ASN1_UTIL_DIR)/libipaasn1.la \ + $(NULL) libipa_pwd_extop_la_SOURCES = \ authcfg.c \ common.c \ diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c index b87ae0dc7a180008228f31293b49212df80584e8..ceea49cab50b0836c882240f210339e60d26729b 100644 --- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c +++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c @@ -40,6 +40,7 @@ #include "ipapwd.h" #include "util.h" #include "authcfg.h" +#include "ipa_asn1.h" /* * Password Modify - LDAP Extended Operation. @@ -1310,31 +1311,7 @@ free_and_return: return SLAPI_PLUGIN_EXTENDED_SENT_RESULT; } -/* Format of getkeytab request - * - * 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, - * } - */ - -#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) - +/* decode a getkeytab control request using libipaasn1 helpers */ static int decode_getkeytab_request(struct berval *extop, bool *wantold, char **_svcname, char **_password, krb5_key_salt_tuple **kenctypes, @@ -1342,96 +1319,44 @@ static int decode_getkeytab_request(struct berval *extop, bool *wantold, { int rc = LDAP_OPERATIONS_ERROR; char *err_msg = NULL; - BerElement *ber = NULL; - ber_len_t tlen; - ber_tag_t rtag; - ber_tag_t ttag; - ber_tag_t ctag; char *svcname = NULL; char *password = NULL; - ber_int_t enctype; + long *etypes = NULL; + int numtypes = 0; krb5_key_salt_tuple *enctypes = NULL; - int num = 0; - - ber = ber_init(extop); - if (ber == NULL) { - err_msg = "KeytabGet Request decode failed.\n"; - rc = LDAP_PROTOCOL_ERROR; - goto done; - } - - /* check this is a request */ - rtag = ber_peek_tag(ber, &tlen); - if (rtag != GK_REQUEST_NEWKEYS && rtag != GK_REQUEST_CURKEYS) { - LOG_FATAL("ber_peek_tag failed, wrong request type\n"); - err_msg = "Invalid payload.\n"; - rc = LDAP_PROTOCOL_ERROR; - goto done; - } - - /* ber parse code */ - ttag = ber_scanf(ber, "{ta", &ctag, &svcname); - if (ttag == LBER_ERROR || ctag != GKREQ_SVCNAME_TAG) { - LOG_FATAL("ber_scanf failed to decode service name\n"); - err_msg = "Invalid payload.\n"; + bool newkt; + bool ret; + int i; + + ret = ipaasn1_dec_getkt(extop->bv_val, extop->bv_len, &newkt, + &svcname, &password, &etypes, &numtypes); + if (!ret) { + err_msg = "Failed to decode GetKeytab Control.\n"; rc = LDAP_PROTOCOL_ERROR; goto done; } - if (rtag == GK_REQUEST_CURKEYS) { - rc = LDAP_SUCCESS; - goto done; - } - - ttag = ber_peek_tag(ber, &tlen); - if (ttag != GKREQ_ENCTYPES_TAG) { - LOG_FATAL("ber_peek_tag failed to find enctypes\n"); - err_msg = "Invalid payload.\n"; - rc = LDAP_PROTOCOL_ERROR; - goto done; - } - ttag = ber_peek_tag(ber, &tlen); - for (num = 0; ttag == LBER_INTEGER; num++) { - if ((num % 10) == 0) { - /* allocate space for at least 10 more enctypes */ - enctypes = realloc(enctypes, - (num + 10) * sizeof(krb5_key_salt_tuple)); + if (newkt) { + if (numtypes) { + enctypes = malloc(numtypes * sizeof(krb5_key_salt_tuple)); if (!enctypes) { LOG_FATAL("allocation failed\n"); err_msg = "Internal error\n"; rc = LDAP_OPERATIONS_ERROR; goto done; } - } - - ttag = ber_scanf(ber, "i", &enctype); - if (ttag == LBER_ERROR) { - LOG_FATAL("ber_scanf failed to decode enctype\n"); - err_msg = "Invalid payload.\n"; - rc = LDAP_PROTOCOL_ERROR; - goto done; - } - - enctypes[num].ks_enctype = enctype; - enctypes[num].ks_salttype = KRB5_KDB_SALTTYPE_NORMAL; - ttag = ber_peek_tag(ber, &tlen); - } - /* ttag peek done as last step of the previous for loop */ - if (ttag == GKREQ_PASSWORD_TAG) { - /* optional password present */ - ttag = ber_scanf(ber, "a", &password); - if (ttag == LBER_ERROR) { - LOG_FATAL("ber_scanf failed to decode password\n"); - err_msg = "Invalid payload.\n"; - rc = LDAP_PROTOCOL_ERROR; - goto done; + for (i = 0; i < numtypes; i++) { + enctypes[i].ks_enctype = etypes[i]; + enctypes[i].ks_salttype = KRB5_KDB_SALTTYPE_NORMAL; + } } } rc = LDAP_SUCCESS; done: + free(etypes); if (rc != LDAP_SUCCESS) { free(password); free(svcname); @@ -1440,78 +1365,34 @@ done: } else { *_password = password; *_svcname = svcname; - *wantold = (rtag == GK_REQUEST_CURKEYS); + *wantold = (newkt == false); *kenctypes = enctypes; - *num_kenctypes = num; + *num_kenctypes = numtypes; } - if (ber) ber_free(ber, 1); return rc; } -/* Format of getkeytab reply - * - * 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_REPLY_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 2) -#define GKREP_KEY_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 0) -#define GKREP_SALT_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 1) -#define GKREP_S2KPARAMS_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 2) -#define GKREP_KEYTYPE_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 0) -#define GKREP_KEYVALUE_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 1) -#define GKREP_SALTTYPE_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 0) -#define GKREP_SALTVALUE_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 1) - static int encode_getkeytab_reply(krb5_context krbctx, krb5_keyblock *kmkey, int mkvno, krb5_key_data *keys, int num_keys, struct berval **_bvp) { int rc = LDAP_OPERATIONS_ERROR; + struct krb_key_salt ksdata[num_keys]; + struct keys_container ksc = { num_keys, ksdata }; struct berval *bvp = NULL; - BerElement *ber = NULL; - ber_int_t kvno; - krb5_data plain = { 0 }; + int kvno; + bool ret; - ber = ber_alloc(); - if (!ber) { - LOG_OOM(); - goto done; - } + memset(ksdata, '\0', num_keys * sizeof(struct krb_key_salt)); /* uses last key kvno */ kvno = keys[num_keys-1].key_data_kvno; - rc = ber_printf(ber, "t{i{", GK_REPLY_TAG, kvno); - if (rc == -1) { - rc = LDAP_OPERATIONS_ERROR; - LOG_FATAL("Failed to initiate key buffer\n"); - goto done; - } - for (int i = 0; i < num_keys; i++) { krb5_enc_data cipher = { 0 }; + krb5_data plain = { 0 }; krb5_int16 plen; - void *p; /* retrieve plain key */ memcpy(&plen, keys[i].key_data_contents[0], 2); @@ -1521,13 +1402,12 @@ static int encode_getkeytab_reply(krb5_context krbctx, cipher.kvno = mkvno; plain.length = le16toh(plen); - p = realloc(plain.data, plain.length); - if (!p) { + plain.data = malloc(plain.length); + if (!plain.data) { LOG_FATAL("Failed to allocate plain buffer\n"); rc = LDAP_OPERATIONS_ERROR; goto done; } - plain.data = p; rc = krb5_c_decrypt(krbctx, kmkey, 0, 0, &cipher, &plain); if (rc) { @@ -1536,68 +1416,37 @@ static int encode_getkeytab_reply(krb5_context krbctx, goto done; } - rc = ber_printf(ber, - "{t{tito}", - GKREP_KEY_TAG, - GKREP_KEYTYPE_TAG, - (ber_int_t)keys[i].key_data_type[0], - GKREP_KEYVALUE_TAG, - plain.data, (ber_len_t)plain.length); - if (rc == -1) { - LOG_FATAL("Failed to encode key data\n"); - rc = LDAP_OPERATIONS_ERROR; - goto done; - } + ksc.ksdata[i].enctype = keys[i].key_data_type[0]; + ksc.ksdata[i].key.enctype = keys[i].key_data_type[0]; + ksc.ksdata[i].key.contents = (void *)plain.data; + ksc.ksdata[i].key.length = plain.length; /* if salt available, add it */ if (keys[i].key_data_length[1] != 0) { - rc = ber_printf(ber, - "t{tito}", - GKREP_SALT_TAG, - GKREP_SALTTYPE_TAG, - (ber_int_t)keys[i].key_data_type[1], - GKREP_SALTVALUE_TAG, - keys[i].key_data_contents[1], - (ber_len_t)keys[i].key_data_length[1]); - if (rc == -1) { - LOG_FATAL("Failed to encode salt data\n"); - rc = LDAP_OPERATIONS_ERROR; - goto done; - } - } - - rc = ber_printf(ber, "}"); - if (rc == -1) { - LOG_FATAL("Failed to encode data\n"); - rc = LDAP_OPERATIONS_ERROR; - goto done; + ksc.ksdata[i].salttype = keys[i].key_data_type[1]; + ksc.ksdata[i].salt.data = (void *)keys[i].key_data_contents[1]; + ksc.ksdata[i].salt.length = keys[i].key_data_length[1]; } } - rc = ber_printf(ber, "}}"); - if (rc == -1) { - LOG_FATAL("Failed to terminate key buffer\n"); - rc = LDAP_OPERATIONS_ERROR; - goto done; - } + bvp = calloc(1, sizeof(struct berval)); + if (!bvp) goto done; - rc = ber_flatten(ber, &bvp); - if (rc == -1) { - LOG_FATAL("Failed to encode key buffer\n"); - rc = LDAP_OPERATIONS_ERROR; - goto done; - } + ret = ipaasn1_enc_getktreply(kvno, &ksc, + (void **)&bvp->bv_val, &bvp->bv_len); + if (!ret) goto done; rc = LDAP_SUCCESS; done: + for (int i = 0; i < ksc.nkeys; i ++) { + free(ksc.ksdata[i].key.contents); + } if (rc != LDAP_SUCCESS) { if (bvp) ber_bvfree(bvp); } else { *_bvp = bvp; } - if (ber) ber_free(ber, 1); - free(plain.data); return rc; } diff --git a/ipa-client/Makefile.am b/ipa-client/Makefile.am index 2df175e53b2a547acdad546db182b38011becd06..b9c7020f3b687b3c0030ed5166625e6ef07e2fa4 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 34625622d3e3bb64866b3b0b1a58d29e33f11a7d..78da8e6e413b8becbd4c75422abffb670050f446 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 bb43c333dca6560807a120103a1cb535fa87b76a..15255d6a33c8c298f138868ac545d4ebea415fe5 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); -- 2.1.0