summaryrefslogtreecommitdiffstats
path: root/asn1/ipa_asn1.c
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2014-11-13 11:31:09 -0500
committerSimo Sorce <simo@redhat.com>2014-11-20 10:52:13 -0500
commitc6afc489a1c9d86fd593bd47c4a8dae6d9a008d2 (patch)
tree27ad9cc99e3c8e38b8df1adacb3cca5e3f8f1e43 /asn1/ipa_asn1.c
parentb170851058d6712442d553ef3d11ecd21b282443 (diff)
downloadfreeipa-c6afc489a1c9d86fd593bd47c4a8dae6d9a008d2.tar.gz
freeipa-c6afc489a1c9d86fd593bd47c4a8dae6d9a008d2.tar.xz
freeipa-c6afc489a1c9d86fd593bd47c4a8dae6d9a008d2.zip
Add asn1c generated code for keytab controls
Instead of manually encoding controls, use an actual asn1 compiler. The file asn1/asn1c/ipa.asn1 will contain ipa modules. The generated code is committed to the tree and built into a static library that is linked to the code that uses it. The first module implements the GetKeytabControl control. Related: 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 'asn1/ipa_asn1.c')
-rw-r--r--asn1/ipa_asn1.c229
1 files changed, 229 insertions, 0 deletions
diff --git a/asn1/ipa_asn1.c b/asn1/ipa_asn1.c
new file mode 100644
index 000000000..50851a804
--- /dev/null
+++ b/asn1/ipa_asn1.c
@@ -0,0 +1,229 @@
+#include <stdbool.h>
+#include <sys/types.h>
+#include "ipa_asn1.h"
+#include "GetKeytabControl.h"
+
+static bool encode_GetKeytabControl(GetKeytabControl_t *gkctrl,
+ void **buf, size_t *len)
+{
+ asn_enc_rval_t rval;
+ char *buffer = NULL;
+ size_t buflen;
+ bool ret = false;
+
+ /* dry run to compute the size */
+ rval = der_encode(&asn_DEF_GetKeytabControl, gkctrl, NULL, NULL);
+ if (rval.encoded == -1) goto done;
+
+ buflen = rval.encoded;
+ buffer = malloc(buflen);
+ if (!buffer) goto done;
+
+ /* now for real */
+ rval = der_encode_to_buffer(&asn_DEF_GetKeytabControl,
+ gkctrl, buffer, buflen);
+ if (rval.encoded == -1) goto done;
+
+ *buf = buffer;
+ *len = buflen;
+ ret = true;
+
+done:
+ if (!ret) {
+ free(buffer);
+ }
+ return ret;
+}
+
+bool ipaasn1_enc_getkt(bool newkt, const char *princ, const char *pwd,
+ long *etypes, int numtypes, void **buf, size_t *len)
+{
+ GetKeytabControl_t gkctrl = { 0 };
+ bool ret = false;
+
+ if (newkt) {
+ gkctrl.present = GetKeytabControl_PR_newkeys;
+ if (OCTET_STRING_fromString(&gkctrl.choice.newkeys.serviceIdentity,
+ princ) != 0) goto done;
+
+ for (int i = 0; i < numtypes; i++) {
+ long *tmp;
+ tmp = malloc(sizeof(long));
+ if (!tmp) goto done;
+ *tmp = etypes[i];
+ ASN_SEQUENCE_ADD(&gkctrl.choice.newkeys.enctypes.list, tmp);
+ }
+
+ if (pwd) {
+ gkctrl.choice.newkeys.password =
+ OCTET_STRING_new_fromBuf(&asn_DEF_OCTET_STRING, pwd, -1);
+ if (!gkctrl.choice.newkeys.password) goto done;
+ }
+ } else {
+ gkctrl.present = GetKeytabControl_PR_curkeys;
+ if (OCTET_STRING_fromString(&gkctrl.choice.curkeys.serviceIdentity,
+ princ) != 0) goto done;
+ }
+
+ ret = encode_GetKeytabControl(&gkctrl, buf, len);
+
+done:
+ ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_GetKeytabControl, &gkctrl);
+ return ret;
+}
+
+bool ipaasn1_enc_getktreply(int kvno, struct keys_container *keys,
+ void **buf, size_t *len)
+{
+ GetKeytabControl_t gkctrl = { 0 };
+ bool ret = false;
+
+ gkctrl.present = GetKeytabControl_PR_reply;
+ gkctrl.choice.reply.newkvno = kvno;
+
+ for (int i = 0; i < keys->nkeys; i++) {
+ KrbKey_t *KK;
+ KK = calloc(1, sizeof(KrbKey_t));
+ if (!KK) goto done;
+ KK->key.type = keys->ksdata[i].key.enctype;
+ KK->key.value.buf = malloc(keys->ksdata[i].key.length);
+ if (!KK->key.value.buf) goto done;
+ memcpy(KK->key.value.buf,
+ keys->ksdata[i].key.contents, keys->ksdata[i].key.length);
+ KK->key.value.size = keys->ksdata[i].key.length;
+
+ if (keys->ksdata[i].salt.data != NULL) {
+ KK->salt = calloc(1, sizeof(TypeValuePair_t));
+ if (!KK->salt) goto done;
+ KK->salt->type = keys->ksdata[i].salttype;
+ KK->salt->value.buf = malloc(keys->ksdata[i].salt.length);
+ if (!KK->salt->value.buf) goto done;
+ memcpy(KK->salt->value.buf,
+ keys->ksdata[i].salt.data, keys->ksdata[i].salt.length);
+ KK->salt->value.size = keys->ksdata[i].salt.length;
+ }
+
+ /* KK->key.s2kparams not used for now */
+
+ ASN_SEQUENCE_ADD(&gkctrl.choice.reply.keys.list, KK);
+ }
+
+ ret = encode_GetKeytabControl(&gkctrl, buf, len);
+
+done:
+ ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_GetKeytabControl, &gkctrl);
+ return ret;
+}
+
+static GetKeytabControl_t *decode_GetKeytabControl(void *buf, size_t len)
+{
+ GetKeytabControl_t *gkctrl = NULL;
+ asn_dec_rval_t rval;
+
+ rval = ber_decode(NULL, &asn_DEF_GetKeytabControl,
+ (void **)&gkctrl, buf, len);
+ if (rval.code == RC_OK) {
+ return gkctrl;
+ }
+ return NULL;
+}
+
+bool ipaasn1_dec_getkt(void *buf, size_t len, bool *newkt,
+ char **princ, char **pwd, long **etypes, int *numtypes)
+{
+ GetKeytabControl_t *gkctrl;
+ bool ret = false;
+ int num;
+
+ gkctrl = decode_GetKeytabControl(buf, len);
+ if (!gkctrl) return false;
+
+ switch (gkctrl->present) {
+ case GetKeytabControl_PR_newkeys:
+ *newkt = true;
+ *princ = strndup((char *)gkctrl->choice.newkeys.serviceIdentity.buf,
+ gkctrl->choice.newkeys.serviceIdentity.size);
+ if (!*princ) goto done;
+
+ num = gkctrl->choice.newkeys.enctypes.list.count;
+ *etypes = malloc(num * sizeof(long));
+ *numtypes = 0;
+ if (!*etypes) goto done;
+ for (int i = 0; i < num; i++) {
+ (*etypes)[i] = *gkctrl->choice.newkeys.enctypes.list.array[i];
+ (*numtypes)++;
+ }
+
+ if (gkctrl->choice.newkeys.password) {
+ *pwd = strndup((char *)gkctrl->choice.newkeys.password->buf,
+ gkctrl->choice.newkeys.password->size);
+ if (!*pwd) goto done;
+ }
+ break;
+ case GetKeytabControl_PR_curkeys:
+ *newkt = false;
+ *princ = strndup((char *)gkctrl->choice.curkeys.serviceIdentity.buf,
+ gkctrl->choice.curkeys.serviceIdentity.size);
+ if (!*princ) goto done;
+ break;
+ default:
+ goto done;
+ }
+
+ ret = true;
+
+done:
+ ASN_STRUCT_FREE(asn_DEF_GetKeytabControl, gkctrl);
+ return ret;
+}
+
+bool ipaasn1_dec_getktreply(void *buf, size_t len,
+ int *kvno, struct keys_container *keys)
+{
+ GetKeytabControl_t *gkctrl;
+ struct KrbKey *KK;
+ bool ret = false;
+ int nkeys;
+
+ gkctrl = decode_GetKeytabControl(buf, len);
+ if (!gkctrl) return false;
+
+ if (gkctrl->present != GetKeytabControl_PR_reply) goto done;
+
+ *kvno = gkctrl->choice.reply.newkvno;
+
+ nkeys = gkctrl->choice.reply.keys.list.count;
+
+ keys->nkeys = 0;
+ keys->ksdata = calloc(nkeys, sizeof(struct krb_key_salt));
+ if (!keys->ksdata) goto done;
+
+ for (int i = 0; i < nkeys; i++) {
+ KK = gkctrl->choice.reply.keys.list.array[i];
+ keys->ksdata[i].enctype = KK->key.type;
+ keys->ksdata[i].key.enctype = KK->key.type;
+ keys->ksdata[i].key.contents = malloc(KK->key.value.size);
+ if (!keys->ksdata[i].key.contents) goto done;
+ memcpy(keys->ksdata[i].key.contents,
+ KK->key.value.buf, KK->key.value.size);
+ keys->ksdata[i].key.length = KK->key.value.size;
+
+ if (KK->salt) {
+ keys->ksdata[i].salttype = KK->salt->type;
+ keys->ksdata[i].salt.data = malloc(KK->salt->value.size);
+ if (!keys->ksdata[i].salt.data) goto done;
+ memcpy(keys->ksdata[i].salt.data,
+ KK->salt->value.buf, KK->salt->value.size);
+ keys->ksdata[i].salt.length = KK->salt->value.size;
+ }
+
+ /* KK->s2kparams is ignored for now */
+ keys->nkeys++;
+ }
+
+ ret = true;
+
+done:
+ ASN_STRUCT_FREE(asn_DEF_GetKeytabControl, gkctrl);
+ return ret;
+}