summaryrefslogtreecommitdiff
path: root/usr/src/lib/libldap4/common/controls.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libldap4/common/controls.c')
-rw-r--r--usr/src/lib/libldap4/common/controls.c291
1 files changed, 291 insertions, 0 deletions
diff --git a/usr/src/lib/libldap4/common/controls.c b/usr/src/lib/libldap4/common/controls.c
new file mode 100644
index 0000000000..bd95409eeb
--- /dev/null
+++ b/usr/src/lib/libldap4/common/controls.c
@@ -0,0 +1,291 @@
+/*
+ *
+ * Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ *
+ * Comments:
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <string.h>
+#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);
+}