10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * 3*3857Sstevel * Copyright 1999 Sun Microsystems, Inc. All rights reserved. 4*3857Sstevel * Use is subject to license terms. 50Sstevel@tonic-gate * 60Sstevel@tonic-gate * 70Sstevel@tonic-gate * Comments: 80Sstevel@tonic-gate * 90Sstevel@tonic-gate */ 100Sstevel@tonic-gate 110Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 120Sstevel@tonic-gate 130Sstevel@tonic-gate #include <stdio.h> 140Sstevel@tonic-gate #include <string.h> 150Sstevel@tonic-gate #include "lber.h" 160Sstevel@tonic-gate #include "ldap.h" 170Sstevel@tonic-gate #include "ldap-private.h" 180Sstevel@tonic-gate #include "ldap-int.h" 190Sstevel@tonic-gate 200Sstevel@tonic-gate static int ldap_control_copy_contents(LDAPControl *, LDAPControl *); 210Sstevel@tonic-gate 220Sstevel@tonic-gate void ldap_control_free (LDAPControl *ctrl) 230Sstevel@tonic-gate { 240Sstevel@tonic-gate if (ctrl != NULL){ 250Sstevel@tonic-gate if (ctrl->ldctl_oid) 260Sstevel@tonic-gate free (ctrl->ldctl_oid); 270Sstevel@tonic-gate if (ctrl->ldctl_value.bv_val != NULL) 280Sstevel@tonic-gate free (ctrl->ldctl_value.bv_val); 290Sstevel@tonic-gate free ((char *)ctrl); 300Sstevel@tonic-gate } 310Sstevel@tonic-gate return; 320Sstevel@tonic-gate } 330Sstevel@tonic-gate 340Sstevel@tonic-gate void ldap_controls_free (LDAPControl **ctrls) 350Sstevel@tonic-gate { 360Sstevel@tonic-gate int i; 370Sstevel@tonic-gate 380Sstevel@tonic-gate if (ctrls == NULL) 390Sstevel@tonic-gate return; 400Sstevel@tonic-gate 410Sstevel@tonic-gate for (i = 0; ctrls[i] != NULL; i++){ 420Sstevel@tonic-gate ldap_control_free(ctrls[i]); 430Sstevel@tonic-gate } 440Sstevel@tonic-gate free((char *)ctrls); 450Sstevel@tonic-gate } 460Sstevel@tonic-gate 470Sstevel@tonic-gate LDAPControl * ldap_control_dup(LDAPControl *ctrl) 480Sstevel@tonic-gate { 490Sstevel@tonic-gate LDAPControl *newctrl; 500Sstevel@tonic-gate 510Sstevel@tonic-gate if ((newctrl = (LDAPControl *)calloc(1, sizeof(LDAPControl))) == NULL) 520Sstevel@tonic-gate return (NULL); 530Sstevel@tonic-gate 540Sstevel@tonic-gate if (ldap_control_copy_contents(newctrl, ctrl) != LDAP_SUCCESS) { 550Sstevel@tonic-gate free(newctrl); 560Sstevel@tonic-gate return (NULL); 570Sstevel@tonic-gate } 580Sstevel@tonic-gate 590Sstevel@tonic-gate return(newctrl); 600Sstevel@tonic-gate } 610Sstevel@tonic-gate 620Sstevel@tonic-gate 630Sstevel@tonic-gate static int ldap_control_copy_contents(LDAPControl *ctrl_dst, 640Sstevel@tonic-gate LDAPControl *ctrl_src) 650Sstevel@tonic-gate { 660Sstevel@tonic-gate size_t len; 670Sstevel@tonic-gate 680Sstevel@tonic-gate if (NULL == ctrl_dst || NULL == ctrl_src) { 690Sstevel@tonic-gate return (LDAP_PARAM_ERROR); 700Sstevel@tonic-gate } 710Sstevel@tonic-gate 720Sstevel@tonic-gate ctrl_dst->ldctl_iscritical = ctrl_src->ldctl_iscritical; 730Sstevel@tonic-gate 740Sstevel@tonic-gate /* fill in the fields of this new control */ 750Sstevel@tonic-gate if ((ctrl_dst->ldctl_oid = strdup(ctrl_src->ldctl_oid)) == NULL) { 760Sstevel@tonic-gate return (LDAP_NO_MEMORY); 770Sstevel@tonic-gate } 780Sstevel@tonic-gate 790Sstevel@tonic-gate len = (size_t)(ctrl_src->ldctl_value).bv_len; 800Sstevel@tonic-gate if (ctrl_src->ldctl_value.bv_val == NULL || len <= 0) { 810Sstevel@tonic-gate ctrl_dst->ldctl_value.bv_len = 0; 820Sstevel@tonic-gate ctrl_dst->ldctl_value.bv_val = NULL; 830Sstevel@tonic-gate } else { 840Sstevel@tonic-gate ctrl_dst->ldctl_value.bv_len = len; 850Sstevel@tonic-gate if ((ctrl_dst->ldctl_value.bv_val = malloc(len)) 860Sstevel@tonic-gate == NULL) { 870Sstevel@tonic-gate free(ctrl_dst->ldctl_oid); 880Sstevel@tonic-gate return (LDAP_NO_MEMORY); 890Sstevel@tonic-gate } 900Sstevel@tonic-gate SAFEMEMCPY(ctrl_dst->ldctl_value.bv_val, 910Sstevel@tonic-gate ctrl_src->ldctl_value.bv_val, len); 920Sstevel@tonic-gate } 930Sstevel@tonic-gate 940Sstevel@tonic-gate return (LDAP_SUCCESS); 950Sstevel@tonic-gate } 960Sstevel@tonic-gate 970Sstevel@tonic-gate 980Sstevel@tonic-gate LDAPControl ** ldap_controls_dup(LDAPControl ** ctrls) 990Sstevel@tonic-gate { 1000Sstevel@tonic-gate int i; 1010Sstevel@tonic-gate LDAPControl **newctrls; 1020Sstevel@tonic-gate 1030Sstevel@tonic-gate for (i = 0; ctrls[i] != NULL; i++); 1040Sstevel@tonic-gate newctrls = (LDAPControl **)calloc(i+1, sizeof(LDAPControl*)); 1050Sstevel@tonic-gate if (newctrls == NULL) { 1060Sstevel@tonic-gate return (NULL); 1070Sstevel@tonic-gate } 1080Sstevel@tonic-gate 1090Sstevel@tonic-gate for (i = 0; ctrls[i] != NULL; i++) { 1100Sstevel@tonic-gate newctrls[i] = ldap_control_dup(ctrls[i]); 1110Sstevel@tonic-gate if (newctrls[i] == NULL) { 1120Sstevel@tonic-gate ldap_controls_free(newctrls); 1130Sstevel@tonic-gate return (NULL); 1140Sstevel@tonic-gate } 1150Sstevel@tonic-gate } 1160Sstevel@tonic-gate return (newctrls); 1170Sstevel@tonic-gate } 1180Sstevel@tonic-gate 1190Sstevel@tonic-gate int ldap_controls_code (BerElement *ber, LDAPControl **ctrls) 1200Sstevel@tonic-gate { 1210Sstevel@tonic-gate int i, rc; 1220Sstevel@tonic-gate 1230Sstevel@tonic-gate if (ctrls && ctrls[0]){ 1240Sstevel@tonic-gate rc = ber_printf(ber, "t{", LDAP_TAG_CONTROL_LIST); 1250Sstevel@tonic-gate if (rc == -1){ 1260Sstevel@tonic-gate ber_free(ber, 1); 1270Sstevel@tonic-gate return(LDAP_ENCODING_ERROR); 1280Sstevel@tonic-gate } 1290Sstevel@tonic-gate 1300Sstevel@tonic-gate for (i = 0; ctrls[i] != NULL; i++){ 1310Sstevel@tonic-gate rc = ber_printf(ber, "{s", ctrls[i]->ldctl_oid); 1320Sstevel@tonic-gate if (rc == -1){ 1330Sstevel@tonic-gate ber_free(ber, 1); 1340Sstevel@tonic-gate return(LDAP_ENCODING_ERROR); 1350Sstevel@tonic-gate } 1360Sstevel@tonic-gate if (ctrls[i]->ldctl_iscritical){ 1370Sstevel@tonic-gate rc = ber_printf(ber, "b", ctrls[i]->ldctl_iscritical); 1380Sstevel@tonic-gate if (rc == -1){ 1390Sstevel@tonic-gate ber_free(ber, 1); 1400Sstevel@tonic-gate return(LDAP_ENCODING_ERROR); 1410Sstevel@tonic-gate } 1420Sstevel@tonic-gate } 1430Sstevel@tonic-gate 1440Sstevel@tonic-gate if (ctrls[i]->ldctl_value.bv_val) 1450Sstevel@tonic-gate rc = ber_printf(ber, "o}", ctrls[i]->ldctl_value.bv_val, ctrls[i]->ldctl_value.bv_len); 1460Sstevel@tonic-gate else 1470Sstevel@tonic-gate rc = ber_printf(ber, "}"); 1480Sstevel@tonic-gate if (rc == -1){ 1490Sstevel@tonic-gate ber_free(ber, 1); 1500Sstevel@tonic-gate return(LDAP_ENCODING_ERROR); 1510Sstevel@tonic-gate } 1520Sstevel@tonic-gate } 1530Sstevel@tonic-gate 1540Sstevel@tonic-gate rc = ber_printf(ber, "}"); 1550Sstevel@tonic-gate if (rc == -1){ 1560Sstevel@tonic-gate ber_free(ber, 1); 1570Sstevel@tonic-gate return(LDAP_ENCODING_ERROR); 1580Sstevel@tonic-gate } 1590Sstevel@tonic-gate } 1600Sstevel@tonic-gate return (LDAP_SUCCESS); 1610Sstevel@tonic-gate } 1620Sstevel@tonic-gate 1630Sstevel@tonic-gate /* Decode the sequence of control from the ber, return a NULL terminated list of LDAPControl* */ 1640Sstevel@tonic-gate LDAPControl ** ldap_controls_decode(BerElement *ber, int *errcode) 1650Sstevel@tonic-gate { 1660Sstevel@tonic-gate LDAPControl ** ctrls = NULL; 1670Sstevel@tonic-gate 1680Sstevel@tonic-gate char *opaque; 1690Sstevel@tonic-gate unsigned int tag, len; 1700Sstevel@tonic-gate int i = 0, count = 0; 1710Sstevel@tonic-gate 1720Sstevel@tonic-gate BerElement tmpber = *ber; 1730Sstevel@tonic-gate 1740Sstevel@tonic-gate for (tag = ber_first_element(&tmpber, &len, &opaque); 1750Sstevel@tonic-gate tag != LBER_DEFAULT; 1760Sstevel@tonic-gate tag = ber_next_element(&tmpber, &len, opaque )) { 1770Sstevel@tonic-gate count ++; 1780Sstevel@tonic-gate ber_skip_tag(&tmpber, &len); 1790Sstevel@tonic-gate } 1800Sstevel@tonic-gate 1810Sstevel@tonic-gate 1820Sstevel@tonic-gate if ((ctrls = (LDAPControl **)calloc(count + 1, sizeof(LDAPControl *))) == NULL){ 1830Sstevel@tonic-gate *errcode = LDAP_NO_MEMORY; 1840Sstevel@tonic-gate return(NULL); 1850Sstevel@tonic-gate } 1860Sstevel@tonic-gate 1870Sstevel@tonic-gate for (tag = ber_first_element(ber, &len, &opaque ); 1880Sstevel@tonic-gate tag != LBER_DEFAULT; 1890Sstevel@tonic-gate tag = ber_next_element (ber, &len, opaque )) { 1900Sstevel@tonic-gate LDAPControl *aCtrl; 1910Sstevel@tonic-gate unsigned int ttag, tlen; 1920Sstevel@tonic-gate 1930Sstevel@tonic-gate if ((aCtrl = (LDAPControl *)calloc(1, sizeof(LDAPControl))) == NULL) { 1940Sstevel@tonic-gate *errcode = LDAP_NO_MEMORY; 1950Sstevel@tonic-gate ldap_controls_free(ctrls); 1960Sstevel@tonic-gate return (NULL); 1970Sstevel@tonic-gate } 1980Sstevel@tonic-gate if (ber_scanf(ber, "{a", &aCtrl->ldctl_oid) == LBER_ERROR){ 1990Sstevel@tonic-gate *errcode = LDAP_PROTOCOL_ERROR; 2000Sstevel@tonic-gate free(aCtrl); 2010Sstevel@tonic-gate ldap_controls_free(ctrls); 2020Sstevel@tonic-gate return (NULL); 2030Sstevel@tonic-gate } 2040Sstevel@tonic-gate aCtrl->ldctl_iscritical = 0; 2050Sstevel@tonic-gate ttag = ber_peek_tag(ber, &tlen); 2060Sstevel@tonic-gate if (ttag == 0x01) { /* Boolean : criticality */ 2070Sstevel@tonic-gate if (ber_scanf(ber, "b", &aCtrl->ldctl_iscritical) == LBER_ERROR){ 2080Sstevel@tonic-gate *errcode = LDAP_PROTOCOL_ERROR; 2090Sstevel@tonic-gate free(aCtrl); 2100Sstevel@tonic-gate ldap_controls_free(ctrls); 2110Sstevel@tonic-gate return (NULL); 2120Sstevel@tonic-gate } 2130Sstevel@tonic-gate ttag = ber_peek_tag(ber, &tlen); 2140Sstevel@tonic-gate } 2150Sstevel@tonic-gate if (ttag == 0x04) { /* Octet string : value (it's optional)*/ 2160Sstevel@tonic-gate if (ber_scanf(ber, "o", &aCtrl->ldctl_value) == LBER_ERROR){ 2170Sstevel@tonic-gate *errcode = LDAP_PROTOCOL_ERROR; 2180Sstevel@tonic-gate free(aCtrl); 2190Sstevel@tonic-gate ldap_controls_free(ctrls); 2200Sstevel@tonic-gate return (NULL); 2210Sstevel@tonic-gate } 2220Sstevel@tonic-gate 2230Sstevel@tonic-gate } else if (ttag != LBER_DEFAULT){ 2240Sstevel@tonic-gate *errcode = LDAP_PROTOCOL_ERROR; 2250Sstevel@tonic-gate free(aCtrl); 2260Sstevel@tonic-gate ldap_controls_free(ctrls); 2270Sstevel@tonic-gate return (NULL); 2280Sstevel@tonic-gate } 2290Sstevel@tonic-gate 2300Sstevel@tonic-gate if (ber_scanf(ber, "}") == LBER_ERROR){ 2310Sstevel@tonic-gate *errcode = LDAP_PROTOCOL_ERROR; 2320Sstevel@tonic-gate free(aCtrl); 2330Sstevel@tonic-gate ldap_controls_free(ctrls); 2340Sstevel@tonic-gate return (NULL); 2350Sstevel@tonic-gate } 2360Sstevel@tonic-gate /* add aCtrl in ctrls */ 2370Sstevel@tonic-gate ctrls[i++] = aCtrl; 2380Sstevel@tonic-gate } 2390Sstevel@tonic-gate return (ctrls); 2400Sstevel@tonic-gate } 2410Sstevel@tonic-gate 2420Sstevel@tonic-gate /* build an allocated LDAPv3 control. Returns an LDAP error code. */ 2430Sstevel@tonic-gate int ldap_build_control(char *oid, BerElement *ber, int freeber, 2440Sstevel@tonic-gate char iscritical, LDAPControl **ctrlp) 2450Sstevel@tonic-gate { 2460Sstevel@tonic-gate int rc; 2470Sstevel@tonic-gate struct berval *bvp; 2480Sstevel@tonic-gate 2490Sstevel@tonic-gate if (ber == NULL) { 2500Sstevel@tonic-gate bvp = NULL; 2510Sstevel@tonic-gate } else { 2520Sstevel@tonic-gate /* allocate struct berval with contents of the BER encoding */ 2530Sstevel@tonic-gate rc = ber_flatten(ber, &bvp); 2540Sstevel@tonic-gate if (freeber) { 2550Sstevel@tonic-gate ber_free(ber, 1); 2560Sstevel@tonic-gate } 2570Sstevel@tonic-gate if (rc == -1) { 2580Sstevel@tonic-gate return (LDAP_NO_MEMORY); 2590Sstevel@tonic-gate } 2600Sstevel@tonic-gate } 2610Sstevel@tonic-gate 2620Sstevel@tonic-gate /* allocate the new control structure */ 2630Sstevel@tonic-gate if ((*ctrlp = (LDAPControl *)calloc(1, sizeof (LDAPControl))) 2640Sstevel@tonic-gate == NULL) { 2650Sstevel@tonic-gate if (bvp != NULL) { 2660Sstevel@tonic-gate ber_bvfree(bvp); 2670Sstevel@tonic-gate } 2680Sstevel@tonic-gate return (LDAP_NO_MEMORY); 2690Sstevel@tonic-gate } 2700Sstevel@tonic-gate 2710Sstevel@tonic-gate /* fill in the fields of this new control */ 2720Sstevel@tonic-gate (*ctrlp)->ldctl_iscritical = iscritical; 2730Sstevel@tonic-gate if (((*ctrlp)->ldctl_oid = strdup(oid)) == NULL) { 2740Sstevel@tonic-gate free(*ctrlp); 2750Sstevel@tonic-gate *ctrlp = NULL; 2760Sstevel@tonic-gate if (bvp != NULL) { 2770Sstevel@tonic-gate ber_bvfree(bvp); 2780Sstevel@tonic-gate } 2790Sstevel@tonic-gate return (LDAP_NO_MEMORY); 2800Sstevel@tonic-gate } 2810Sstevel@tonic-gate 2820Sstevel@tonic-gate if (bvp == NULL) { 2830Sstevel@tonic-gate (*ctrlp)->ldctl_value.bv_len = 0; 2840Sstevel@tonic-gate (*ctrlp)->ldctl_value.bv_val = NULL; 2850Sstevel@tonic-gate } else { 2860Sstevel@tonic-gate (*ctrlp)->ldctl_value = *bvp; /* struct copy */ 2870Sstevel@tonic-gate free(bvp); /* free container, not contents! */ 2880Sstevel@tonic-gate } 2890Sstevel@tonic-gate 2900Sstevel@tonic-gate return (LDAP_SUCCESS); 2910Sstevel@tonic-gate } 292