/* * * Copyright 1999 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * * Comments: * */ #pragma ident "%Z%%M% %I% %E% SMI" #include #include #include "lber.h" #include "ldap.h" #include "ldap-private.h" #include "ldap-int.h" static int ldap_control_copy_contents(LDAPControl *, LDAPControl *); void ldap_control_free (LDAPControl *ctrl) { if (ctrl != NULL){ if (ctrl->ldctl_oid) free (ctrl->ldctl_oid); if (ctrl->ldctl_value.bv_val != NULL) free (ctrl->ldctl_value.bv_val); free ((char *)ctrl); } return; } void ldap_controls_free (LDAPControl **ctrls) { int i; if (ctrls == NULL) return; for (i = 0; ctrls[i] != NULL; i++){ ldap_control_free(ctrls[i]); } free((char *)ctrls); } LDAPControl * ldap_control_dup(LDAPControl *ctrl) { LDAPControl *newctrl; if ((newctrl = (LDAPControl *)calloc(1, sizeof(LDAPControl))) == NULL) return (NULL); if (ldap_control_copy_contents(newctrl, ctrl) != LDAP_SUCCESS) { free(newctrl); return (NULL); } return(newctrl); } static int ldap_control_copy_contents(LDAPControl *ctrl_dst, LDAPControl *ctrl_src) { size_t len; if (NULL == ctrl_dst || NULL == ctrl_src) { return (LDAP_PARAM_ERROR); } ctrl_dst->ldctl_iscritical = ctrl_src->ldctl_iscritical; /* fill in the fields of this new control */ if ((ctrl_dst->ldctl_oid = strdup(ctrl_src->ldctl_oid)) == NULL) { return (LDAP_NO_MEMORY); } len = (size_t)(ctrl_src->ldctl_value).bv_len; if (ctrl_src->ldctl_value.bv_val == NULL || len <= 0) { ctrl_dst->ldctl_value.bv_len = 0; ctrl_dst->ldctl_value.bv_val = NULL; } else { ctrl_dst->ldctl_value.bv_len = len; if ((ctrl_dst->ldctl_value.bv_val = malloc(len)) == NULL) { free(ctrl_dst->ldctl_oid); return (LDAP_NO_MEMORY); } SAFEMEMCPY(ctrl_dst->ldctl_value.bv_val, ctrl_src->ldctl_value.bv_val, len); } return (LDAP_SUCCESS); } LDAPControl ** ldap_controls_dup(LDAPControl ** ctrls) { int i; LDAPControl **newctrls; for (i = 0; ctrls[i] != NULL; i++); newctrls = (LDAPControl **)calloc(i+1, sizeof(LDAPControl*)); if (newctrls == NULL) { return (NULL); } for (i = 0; ctrls[i] != NULL; i++) { newctrls[i] = ldap_control_dup(ctrls[i]); if (newctrls[i] == NULL) { ldap_controls_free(newctrls); return (NULL); } } return (newctrls); } int ldap_controls_code (BerElement *ber, LDAPControl **ctrls) { int i, rc; if (ctrls && ctrls[0]){ rc = ber_printf(ber, "t{", LDAP_TAG_CONTROL_LIST); if (rc == -1){ ber_free(ber, 1); return(LDAP_ENCODING_ERROR); } for (i = 0; ctrls[i] != NULL; i++){ rc = ber_printf(ber, "{s", ctrls[i]->ldctl_oid); if (rc == -1){ ber_free(ber, 1); return(LDAP_ENCODING_ERROR); } if (ctrls[i]->ldctl_iscritical){ rc = ber_printf(ber, "b", ctrls[i]->ldctl_iscritical); if (rc == -1){ ber_free(ber, 1); return(LDAP_ENCODING_ERROR); } } if (ctrls[i]->ldctl_value.bv_val) rc = ber_printf(ber, "o}", ctrls[i]->ldctl_value.bv_val, ctrls[i]->ldctl_value.bv_len); else rc = ber_printf(ber, "}"); if (rc == -1){ ber_free(ber, 1); return(LDAP_ENCODING_ERROR); } } rc = ber_printf(ber, "}"); if (rc == -1){ ber_free(ber, 1); return(LDAP_ENCODING_ERROR); } } return (LDAP_SUCCESS); } /* Decode the sequence of control from the ber, return a NULL terminated list of LDAPControl* */ LDAPControl ** ldap_controls_decode(BerElement *ber, int *errcode) { LDAPControl ** ctrls = NULL; char *opaque; unsigned int tag, len; int i = 0, count = 0; BerElement tmpber = *ber; for (tag = ber_first_element(&tmpber, &len, &opaque); tag != LBER_DEFAULT; tag = ber_next_element(&tmpber, &len, opaque )) { count ++; ber_skip_tag(&tmpber, &len); } if ((ctrls = (LDAPControl **)calloc(count + 1, sizeof(LDAPControl *))) == NULL){ *errcode = LDAP_NO_MEMORY; return(NULL); } for (tag = ber_first_element(ber, &len, &opaque ); tag != LBER_DEFAULT; tag = ber_next_element (ber, &len, opaque )) { LDAPControl *aCtrl; unsigned int ttag, tlen; if ((aCtrl = (LDAPControl *)calloc(1, sizeof(LDAPControl))) == NULL) { *errcode = LDAP_NO_MEMORY; ldap_controls_free(ctrls); return (NULL); } if (ber_scanf(ber, "{a", &aCtrl->ldctl_oid) == LBER_ERROR){ *errcode = LDAP_PROTOCOL_ERROR; free(aCtrl); ldap_controls_free(ctrls); return (NULL); } aCtrl->ldctl_iscritical = 0; ttag = ber_peek_tag(ber, &tlen); if (ttag == 0x01) { /* Boolean : criticality */ if (ber_scanf(ber, "b", &aCtrl->ldctl_iscritical) == LBER_ERROR){ *errcode = LDAP_PROTOCOL_ERROR; free(aCtrl); ldap_controls_free(ctrls); return (NULL); } ttag = ber_peek_tag(ber, &tlen); } if (ttag == 0x04) { /* Octet string : value (it's optional)*/ if (ber_scanf(ber, "o", &aCtrl->ldctl_value) == LBER_ERROR){ *errcode = LDAP_PROTOCOL_ERROR; free(aCtrl); ldap_controls_free(ctrls); return (NULL); } } else if (ttag != LBER_DEFAULT){ *errcode = LDAP_PROTOCOL_ERROR; free(aCtrl); ldap_controls_free(ctrls); return (NULL); } if (ber_scanf(ber, "}") == LBER_ERROR){ *errcode = LDAP_PROTOCOL_ERROR; free(aCtrl); ldap_controls_free(ctrls); return (NULL); } /* add aCtrl in ctrls */ ctrls[i++] = aCtrl; } return (ctrls); } /* build an allocated LDAPv3 control. Returns an LDAP error code. */ int ldap_build_control(char *oid, BerElement *ber, int freeber, char iscritical, LDAPControl **ctrlp) { int rc; struct berval *bvp; if (ber == NULL) { bvp = NULL; } else { /* allocate struct berval with contents of the BER encoding */ rc = ber_flatten(ber, &bvp); if (freeber) { ber_free(ber, 1); } if (rc == -1) { return (LDAP_NO_MEMORY); } } /* allocate the new control structure */ if ((*ctrlp = (LDAPControl *)calloc(1, sizeof (LDAPControl))) == NULL) { if (bvp != NULL) { ber_bvfree(bvp); } return (LDAP_NO_MEMORY); } /* fill in the fields of this new control */ (*ctrlp)->ldctl_iscritical = iscritical; if (((*ctrlp)->ldctl_oid = strdup(oid)) == NULL) { free(*ctrlp); *ctrlp = NULL; if (bvp != NULL) { ber_bvfree(bvp); } return (LDAP_NO_MEMORY); } if (bvp == NULL) { (*ctrlp)->ldctl_value.bv_len = 0; (*ctrlp)->ldctl_value.bv_val = NULL; } else { (*ctrlp)->ldctl_value = *bvp; /* struct copy */ free(bvp); /* free container, not contents! */ } return (LDAP_SUCCESS); }