diff options
Diffstat (limited to 'source3/libads/ldap.c')
-rw-r--r-- | source3/libads/ldap.c | 679 |
1 files changed, 302 insertions, 377 deletions
diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c index 9d15c4e33c..e2e351bd4b 100644 --- a/source3/libads/ldap.c +++ b/source3/libads/ldap.c @@ -30,11 +30,6 @@ * * The routines contained here should do the necessary ldap calls for * ads setups. - * - * Important note: attribute names passed into ads_ routines must - * already be in UTF-8 format. We do not convert them because in almost - * all cases, they are just ascii (which is represented with the same - * codepoints in UTF-8). This may have to change at some point **/ /** @@ -50,38 +45,10 @@ ADS_STATUS ads_connect(ADS_STRUCT *ads) ads->last_attempt = time(NULL); - ads->ld = NULL; - - if (ads->ldap_server) { - ads->ld = ldap_open(ads->ldap_server, ads->ldap_port); - } - - /* if that failed then try each of the BDC's in turn */ - if (!ads->ld) { - struct in_addr *ip_list; - int count; - - if (get_dc_list(False, ads->workgroup, &ip_list, &count)) { - int i; - for (i=0;i<count;i++) { - ads->ld = ldap_open(inet_ntoa(ip_list[i]), - ads->ldap_port); - if (ads->ld) break; - } - if (ads->ld) { - SAFE_FREE(ads->ldap_server); - ads->ldap_server = strdup(inet_ntoa(ip_list[i])); - } - free(ip_list); - } - } - + ads->ld = ldap_open(ads->ldap_server, ads->ldap_port); if (!ads->ld) { return ADS_ERROR_SYSTEM(errno); } - - DEBUG(3,("Connected to LDAP server %s\n", ads->ldap_server)); - status = ads_server_info(ads); if (!ADS_ERR_OK(status)) { DEBUG(1,("Failed to get ldap server info\n")); @@ -109,81 +76,6 @@ ADS_STATUS ads_connect(ADS_STRUCT *ads) return ads_sasl_bind(ads); } -/* - Duplicate a struct berval into talloc'ed memory - */ -static struct berval *dup_berval(TALLOC_CTX *ctx, const struct berval *in_val) -{ - struct berval *value; - - if (!in_val) return NULL; - - value = talloc_zero(ctx, sizeof(struct berval)); - if (in_val->bv_len == 0) return value; - - value->bv_len = in_val->bv_len; - value->bv_val = talloc_memdup(ctx, in_val->bv_val, in_val->bv_len); - return value; -} - -/* - Make a values list out of an array of (struct berval *) - */ -static struct berval **ads_dup_values(TALLOC_CTX *ctx, - const struct berval **in_vals) -{ - struct berval **values; - int i; - - if (!in_vals) return NULL; - for (i=0; in_vals[i]; i++); /* count values */ - values = (struct berval **) talloc_zero(ctx, - (i+1)*sizeof(struct berval *)); - if (!values) return NULL; - - for (i=0; in_vals[i]; i++) { - values[i] = dup_berval(ctx, in_vals[i]); - } - return values; -} - -/* - UTF8-encode a values list out of an array of (char *) - */ -static char **ads_push_strvals(TALLOC_CTX *ctx, const char **in_vals) -{ - char **values; - int i; - - if (!in_vals) return NULL; - for (i=0; in_vals[i]; i++); /* count values */ - values = (char ** ) talloc_zero(ctx, (i+1)*sizeof(char *)); - if (!values) return NULL; - - for (i=0; in_vals[i]; i++) { - push_utf8_talloc(ctx, (void **) &values[i], in_vals[i]); - } - return values; -} - -/* - Pull a (char *) array out of a UTF8-encoded values list - */ -static char **ads_pull_strvals(TALLOC_CTX *ctx, const char **in_vals) -{ - char **values; - int i; - - if (!in_vals) return NULL; - for (i=0; in_vals[i]; i++); /* count values */ - values = (char **) talloc_zero(ctx, (i+1)*sizeof(char *)); - if (!values) return NULL; - - for (i=0; in_vals[i]; i++) { - pull_utf8_talloc(ctx, (void **) &values[i], in_vals[i]); - } - return values; -} /** * Do a search with paged results. cookie must be null on the first @@ -192,8 +84,8 @@ static char **ads_pull_strvals(TALLOC_CTX *ctx, const char **in_vals) * @param ads connection to ads server * @param bind_path Base dn for the search * @param scope Scope of search (LDAP_BASE | LDAP_ONE | LDAP_SUBTREE) - * @param exp Search expression - specified in local charset - * @param attrs Attributes to retrieve - specified in utf8 or ascii + * @param exp Search expression + * @param attrs Attributes to retrieve * @param res ** which will contain results - free res* with ads_msgfree() * @param count Number of entries retrieved on this page * @param cookie The paged results cookie to be returned on subsequent calls @@ -204,46 +96,25 @@ ADS_STATUS ads_do_paged_search(ADS_STRUCT *ads, const char *bind_path, const char **attrs, void **res, int *count, void **cookie) { - int rc, i, version; - char *utf8_exp, *utf8_path, **search_attrs; - LDAPControl PagedResults, NoReferrals, *controls[3], **rcontrols; + int rc; + int version; + LDAPControl PagedResults; + LDAPControl NoReferrals; BerElement *cookie_be = NULL; struct berval *cookie_bv= NULL; - TALLOC_CTX *ctx; + LDAPControl *controls[3]; + LDAPControl **rcontrols; + int i; *res = NULL; - if (!(ctx = talloc_init())) - return ADS_ERROR(LDAP_NO_MEMORY); - - /* 0 means the conversion worked but the result was empty - so we only fail if it's negative. In any case, it always - at least nulls out the dest */ - if ((push_utf8_talloc(ctx, (void **) &utf8_exp, exp) < 0) || - (push_utf8_talloc(ctx, (void **) &utf8_path, bind_path) < 0)) { - rc = LDAP_NO_MEMORY; - goto done; - } - - if (!attrs || !(*attrs)) - search_attrs = NULL; - else { - /* This would be the utf8-encoded version...*/ - /* if (!(search_attrs = ads_push_strvals(ctx, attrs))) */ - if (!(str_list_copy(&search_attrs, (char **) attrs))) - { - rc = LDAP_NO_MEMORY; - goto done; - } - } - - - /* Paged results only available on ldap v3 or later */ ldap_get_option(ads->ld, LDAP_OPT_PROTOCOL_VERSION, &version); - if (version < LDAP_VERSION3) { - rc = LDAP_NOT_SUPPORTED; - goto done; - } + + /* Paged results only available on ldap v3 or later, so check + version first before using, since at connect time we're + only v2. Not sure exactly why... */ + if (version < LDAP_VERSION3) + return ADS_ERROR(LDAP_NOT_SUPPORTED); cookie_be = ber_alloc_t(LBER_USE_DER); if (cookie && *cookie) { @@ -272,32 +143,33 @@ ADS_STATUS ads_do_paged_search(ADS_STRUCT *ads, const char *bind_path, *res = NULL; /* we need to disable referrals as the openldap libs don't - handle them and paged results at the same time. Using them - together results in the result record containing the server - page control being removed from the result list (tridge/jmcd) + seem to handle them correctly. They result in the result + record containing the server control being removed from the + result list (tridge) leaving this in despite the control that says don't generate referrals, in case the server doesn't support it (jmcd) */ ldap_set_option(ads->ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF); - rc = ldap_search_ext_s(ads->ld, utf8_path, scope, utf8_exp, - search_attrs, 0, controls, - NULL, NULL, LDAP_NO_LIMIT, (LDAPMessage **)res); + rc = ldap_search_ext_s(ads->ld, bind_path, scope, exp, + (char **) attrs, 0, controls, NULL, + NULL, LDAP_NO_LIMIT, + (LDAPMessage **)res); ber_free(cookie_be, 1); ber_bvfree(cookie_bv); if (rc) { DEBUG(3,("ldap_search_ext_s(%s) -> %s\n", exp, ldap_err2string(rc))); - goto done; + return ADS_ERROR(rc); } rc = ldap_parse_result(ads->ld, *res, NULL, NULL, NULL, NULL, &rcontrols, 0); if (!rcontrols) { - goto done; + return ADS_ERROR(rc); } for (i=0; rcontrols[i]; i++) { @@ -317,12 +189,7 @@ ADS_STATUS ads_do_paged_search(ADS_STRUCT *ads, const char *bind_path, } } ldap_controls_free(rcontrols); - -done: - talloc_destroy(ctx); - /* if/when we decide to utf8-encode attrs, take out this next line */ - str_list_free(&search_attrs); - + return ADS_ERROR(rc); } @@ -367,6 +234,7 @@ ADS_STATUS ads_do_search_all(ADS_STRUCT *ads, const char *bind_path, next = ads_next_entry(ads, msg); ldap_add_result_entry((LDAPMessage **)res, msg); } + /* note that we do not free res2, as the memory is now part of the main returned list */ } @@ -380,15 +248,15 @@ ADS_STATUS ads_do_search_all(ADS_STRUCT *ads, const char *bind_path, * @param ads connection to ads server * @param bind_path Base dn for the search * @param scope Scope of search (LDAP_BASE | LDAP_ONE | LDAP_SUBTREE) - * @param exp Search expression - specified in local charset - * @param attrs Attributes to retrieve - specified in UTF-8 or ascii + * @param exp Search expression + * @param attrs Attributes to retrieve * @param fn Function which takes attr name, values list, and data_area * @param data_area Pointer which is passed to function on each call * @return status of search **/ ADS_STATUS ads_do_search_all_fn(ADS_STRUCT *ads, const char *bind_path, int scope, const char *exp, const char **attrs, - BOOL(*fn)(char *, void **, void *), + void(*fn)(char *, void **, void *), void *data_area) { void *cookie = NULL; @@ -433,42 +301,14 @@ ADS_STATUS ads_do_search(ADS_STRUCT *ads, const char *bind_path, int scope, { struct timeval timeout; int rc; - char *utf8_exp, *utf8_path, **search_attrs = NULL; - TALLOC_CTX *ctx; - - if (!(ctx = talloc_init())) - return ADS_ERROR(LDAP_NO_MEMORY); - - /* 0 means the conversion worked but the result was empty - so we only fail if it's negative. In any case, it always - at least nulls out the dest */ - if ((push_utf8_talloc(ctx, (void **) &utf8_exp, exp) < 0) || - (push_utf8_talloc(ctx, (void **) &utf8_path, bind_path) < 0)) { - rc = LDAP_NO_MEMORY; - goto done; - } - - if (!attrs || !(*attrs)) - search_attrs = NULL; - else { - /* This would be the utf8-encoded version...*/ - /* if (!(search_attrs = ads_push_strvals(ctx, attrs))) */ - if (!(str_list_copy(&search_attrs, (char **) attrs))) - { - rc = LDAP_NO_MEMORY; - goto done; - } - } timeout.tv_sec = ADS_SEARCH_TIMEOUT; timeout.tv_usec = 0; *res = NULL; - /* see the note in ads_do_paged_search - we *must* disable referrals */ - ldap_set_option(ads->ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF); - - rc = ldap_search_ext_s(ads->ld, utf8_path, scope, utf8_exp, - search_attrs, 0, NULL, NULL, + rc = ldap_search_ext_s(ads->ld, + bind_path, scope, + exp, (char **) attrs, 0, NULL, NULL, &timeout, LDAP_NO_LIMIT, (LDAPMessage **)res); if (rc == LDAP_SIZELIMIT_EXCEEDED) { @@ -476,10 +316,6 @@ ADS_STATUS ads_do_search(ADS_STRUCT *ads, const char *bind_path, int scope, rc = 0; } - done: - talloc_destroy(ctx); - /* if/when we decide to utf8-encode attrs, take out this next line */ - str_list_free(&search_attrs); return ADS_ERROR(rc); } /** @@ -531,7 +367,8 @@ void ads_msgfree(ADS_STRUCT *ads, void *msg) **/ void ads_memfree(ADS_STRUCT *ads, void *mem) { - SAFE_FREE(mem); + if (!mem) return; + ldap_memfree(mem); } /** @@ -542,12 +379,7 @@ void ads_memfree(ADS_STRUCT *ads, void *mem) **/ char *ads_get_dn(ADS_STRUCT *ads, void *res) { - char *utf8_dn, *unix_dn; - - utf8_dn = ldap_get_dn(ads->ld, res); - pull_utf8_allocate((void **) &unix_dn, utf8_dn); - ldap_memfree(utf8_dn); - return unix_dn; + return ldap_get_dn(ads->ld, res); } /** @@ -571,6 +403,25 @@ ADS_STATUS ads_find_machine_acct(ADS_STRUCT *ads, void **res, const char *host) return status; } +/* + duplicate an already-assembled list of values so that it can be + freed as part of the standard msgfree call +*/ +static char **ads_dup_values(TALLOC_CTX *ctx, char **values) +{ + char **newvals; + int i; +#define ADS_MAX_NUM_VALUES 32 + + for (i=0; values[i] && i<ADS_MAX_NUM_VALUES; i++); + if (!(newvals = talloc_zero(ctx, (i+1)*sizeof(char *)))) + return NULL; + for (i=0; values[i] && i<ADS_MAX_NUM_VALUES; i++) + newvals[i] = values[i]; + newvals[i] = NULL; + return newvals; +} + /** * Initialize a list of mods to be used in a modify request * @param ctx An initialized TALLOC_CTX @@ -590,29 +441,14 @@ ADS_MODLIST ads_init_mods(TALLOC_CTX *ctx) return mods; } - /* add an attribute to the list, with values list already constructed */ static ADS_STATUS ads_modlist_add(TALLOC_CTX *ctx, ADS_MODLIST *mods, - int mod_op, const char *name, - const void **invals) + int mod_op, const char *name, char **values) { int curmod; LDAPMod **modlist = (LDAPMod **) *mods; - void **values; - - if (!invals) { - values = NULL; - mod_op = LDAP_MOD_DELETE; - } else { - if (mod_op & LDAP_MOD_BVALUES) - values = (void **) ads_dup_values(ctx, - (const struct berval **)invals); - else - values = (void **) ads_push_strvals(ctx, - (const char **) invals); - } /* find the first empty slot */ for (curmod=0; modlist[curmod] && modlist[curmod] != (LDAPMod *) -1; @@ -629,66 +465,217 @@ static ADS_STATUS ads_modlist_add(TALLOC_CTX *ctx, ADS_MODLIST *mods, if (!(modlist[curmod] = talloc_zero(ctx, sizeof(LDAPMod)))) return ADS_ERROR(LDAP_NO_MEMORY); - modlist[curmod]->mod_type = talloc_strdup(ctx, name); + modlist[curmod]->mod_type = name; if (mod_op & LDAP_MOD_BVALUES) modlist[curmod]->mod_bvalues = (struct berval **) values; else - modlist[curmod]->mod_values = (char **) values; + modlist[curmod]->mod_values = values; modlist[curmod]->mod_op = mod_op; return ADS_ERROR(LDAP_SUCCESS); } /** - * Add a single string value to a mod list + * Add an already-constructed list of values to a mod list for an ADD * @param ctx An initialized TALLOC_CTX * @param mods An initialized ADS_MODLIST * @param name The attribute name to add - * @param val The value to add - NULL means DELETE + * @param values Constructed values list to add * @return ADS STATUS indicating success of add **/ -ADS_STATUS ads_mod_str(TALLOC_CTX *ctx, ADS_MODLIST *mods, - const char *name, const char *val) +ADS_STATUS ads_mod_add_list(TALLOC_CTX *ctx, ADS_MODLIST *mods, + char *name, char **values) { - const char *values[2] = {val, NULL}; - if (!val) - return ads_modlist_add(ctx, mods, LDAP_MOD_DELETE, name, NULL); - return ads_modlist_add(ctx, mods, LDAP_MOD_REPLACE, name, - (const void **) values); + char **newvals = ads_dup_values(ctx, values); + if (newvals) + return ads_modlist_add(ctx, mods, LDAP_MOD_ADD, name, newvals); + else + return ADS_ERROR(LDAP_NO_MEMORY); } /** - * Add an array of string values to a mod list + * Add an already-constructed list of values to a mod list for a REPLACE * @param ctx An initialized TALLOC_CTX * @param mods An initialized ADS_MODLIST * @param name The attribute name to add - * @param vals The array of string values to add - NULL means DELETE + * @param values Constructed values list to add * @return ADS STATUS indicating success of add **/ -ADS_STATUS ads_mod_strlist(TALLOC_CTX *ctx, ADS_MODLIST *mods, - const char *name, const char **vals) +ADS_STATUS ads_mod_repl_list(TALLOC_CTX *ctx, ADS_MODLIST *mods, + char *name, char **values) { - if (!vals) + char **newvals; + if (values && *values) { + if (!(newvals = ads_dup_values(ctx, values))) + return ADS_ERROR(LDAP_NO_MEMORY); + else + return ads_modlist_add(ctx, mods, LDAP_MOD_REPLACE, + name, newvals); + } + else return ads_modlist_add(ctx, mods, LDAP_MOD_DELETE, name, NULL); - return ads_modlist_add(ctx, mods, LDAP_MOD_REPLACE, - name, (const void **) vals); } /** - * Add a single ber-encoded value to a mod list + * Add any number of string values to a mod list - for ADD or REPLACE + * @param ctx An initialized TALLOC_CTX + * @param mods An initialized ADS_MODLIST + * @param mod_op Operation to perform (LDAP_MOD_ADD | LDAP_MOD_REPLACE) + * @param name The attribute name to add + * @param ... Any number of values, in (char *) form + * @return ADS STATUS indicating success of add + **/ +ADS_STATUS ads_mod_add_var(TALLOC_CTX *ctx, ADS_MODLIST *mods, + int mod_op, const char *name, ...) +{ + va_list ap; + int num_vals, i, do_op; + char *value, **values; + + /* count the number of values */ + va_start(ap, name); + for (num_vals=0; va_arg(ap, char *); num_vals++); + va_end(ap); + + if (num_vals) { + if (!(values = talloc_zero(ctx, sizeof(char *)*(num_vals+1)))) + return ADS_ERROR(LDAP_NO_MEMORY); + va_start(ap, name); + for (i=0; (value = (char *) va_arg(ap, char *)) && + i < num_vals; i++) + values[i] = value; + va_end(ap); + values[i] = NULL; + do_op = mod_op; + } else { + do_op = LDAP_MOD_DELETE; + values = NULL; + } + return ads_modlist_add(ctx, mods, do_op, name, values); +} + +/** + * Add any number of ber values to a mod list - for ADD or REPLACE * @param ctx An initialized TALLOC_CTX * @param mods An initialized ADS_MODLIST + * @param mod_op Operation to perform (LDAP_MOD_ADD | LDAP_MOD_REPLACE) * @param name The attribute name to add - * @param val The value to add - NULL means DELETE + * @param ... Any number of values, in (struct berval *) form + * @return ADS STATUS indicating success of add + **/ +ADS_STATUS ads_mod_add_ber(TALLOC_CTX *ctx, ADS_MODLIST *mods, + int mod_op, const char *name, ...) +{ + va_list ap; + int num_vals, i, do_op; + char *value, **values; + + /* count the number of values */ + va_start(ap, name); + for (num_vals=0; va_arg(ap, struct berval *); num_vals++); + va_end(ap); + + if (num_vals) { + if (!(values = talloc_zero(ctx, sizeof(struct berval) * + (num_vals + 1)))) + return ADS_ERROR(LDAP_NO_MEMORY); + va_start(ap, name); + for (i=0; (value = (char *) va_arg(ap, char *)) && + i < num_vals; i++) + values[i] = value; + va_end(ap); + values[i] = NULL; + do_op = mod_op; + } else { + do_op = LDAP_MOD_DELETE; + values = NULL; + } + do_op |= LDAP_MOD_BVALUES; + return ads_modlist_add(ctx, mods, do_op, name, values); +} + +/** + * Add a single string value to a mod list - for REPLACE + * @param ctx An initialized TALLOC_CTX + * @param mods An initialized ADS_MODLIST + * @param name The attribute name to replace + * @param val The value to add + * @return ADS STATUS indicating success of add + **/ +ADS_STATUS ads_mod_repl(TALLOC_CTX *ctx, ADS_MODLIST *mods, + char *name, char *val) +{ + if (val) + return ads_mod_add_var(ctx, mods, LDAP_MOD_REPLACE, + name, val, NULL); + else + return ads_mod_add_var(ctx, mods, LDAP_MOD_DELETE, name, NULL); +} + +/** + * Add a single string value to a mod list - for ADD + * @param ctx An initialized TALLOC_CTX + * @param mods An initialized ADS_MODLIST + * @param name The attribute name to add + * @param val The value to add + * @return ADS STATUS indicating success of add + **/ +ADS_STATUS ads_mod_add(TALLOC_CTX *ctx, ADS_MODLIST *mods, + const char *name, const char *val) +{ + return ads_mod_add_var(ctx, mods, LDAP_MOD_ADD, name, val, NULL); +} + +/** + * Add a single berval value to a mod list - for ADD + * @param ctx An initialized TALLOC_CTX + * @param mods An initialized ADS_MODLIST + * @param name The attribute name to add + * @param size The size of of the value + * @param val The value to add + * @return ADS STATUS indicating success of add + **/ +ADS_STATUS ads_mod_add_len(TALLOC_CTX *ctx, ADS_MODLIST *mods, + char *name, size_t size, char *val) +{ + struct berval *bval = NULL; + + if (!(bval = talloc_zero(ctx, sizeof(struct berval *)))) + return ADS_ERROR(LDAP_NO_MEMORY); + if (!(bval->bv_val = talloc_zero(ctx, sizeof(char *)))) + return ADS_ERROR(LDAP_NO_MEMORY); + + bval->bv_val = val; + bval->bv_len = size; + return ads_mod_add_ber(ctx, mods, LDAP_MOD_ADD, name, bval, NULL); +} + +/** + * Add a single berval value to a mod list - for REPLACE + * @param ctx An initialized TALLOC_CTX + * @param mods An initialized ADS_MODLIST + * @param name The attribute name to replace + * @param size The size of of the value + * @param val The value to add * @return ADS STATUS indicating success of add **/ -static ADS_STATUS ads_mod_ber(TALLOC_CTX *ctx, ADS_MODLIST *mods, - const char *name, const struct berval *val) +ADS_STATUS ads_mod_repl_len(TALLOC_CTX *ctx, ADS_MODLIST *mods, + const char *name, size_t size, char *val) { - const struct berval *values[2] = {val, NULL}; + struct berval *bval = NULL; + + if (!(bval = talloc_zero(ctx, sizeof(struct berval *)))) + return ADS_ERROR(LDAP_NO_MEMORY); + if (!val) - return ads_modlist_add(ctx, mods, LDAP_MOD_DELETE, name, NULL); - return ads_modlist_add(ctx, mods, LDAP_MOD_REPLACE|LDAP_MOD_BVALUES, - name, (const void **) values); + return ads_mod_add_ber(ctx, mods, LDAP_MOD_DELETE, name, NULL); + else { + if (!(bval->bv_val = talloc_zero(ctx, sizeof(char *)))) + return ADS_ERROR(LDAP_NO_MEMORY); + bval->bv_val = val; + bval->bv_len = size; + return ads_mod_add_ber(ctx, mods, LDAP_MOD_REPLACE, name, + bval, NULL); + } } /** @@ -701,7 +688,6 @@ static ADS_STATUS ads_mod_ber(TALLOC_CTX *ctx, ADS_MODLIST *mods, ADS_STATUS ads_gen_mod(ADS_STRUCT *ads, const char *mod_dn, ADS_MODLIST mods) { int ret,i; - char *utf8_dn = NULL; /* this control is needed to modify that contains a currently non-existent attribute (but allowable for the object) to run @@ -715,15 +701,12 @@ ADS_STATUS ads_gen_mod(ADS_STRUCT *ads, const char *mod_dn, ADS_MODLIST mods) controls[0] = &PermitModify; controls[1] = NULL; - push_utf8_allocate((void **) &utf8_dn, mod_dn); - /* find the end of the list, marked by NULL or -1 */ for(i=0;(mods[i]!=0)&&(mods[i]!=(LDAPMod *) -1);i++); /* make sure the end of the list is NULL */ mods[i] = NULL; - ret = ldap_modify_ext_s(ads->ld, utf8_dn ? utf8_dn : mod_dn, - (LDAPMod **) mods, controls, NULL); - SAFE_FREE(utf8_dn); + ret = ldap_modify_ext_s(ads->ld, mod_dn, (LDAPMod **) mods, + controls, NULL); return ADS_ERROR(ret); } @@ -736,19 +719,14 @@ ADS_STATUS ads_gen_mod(ADS_STRUCT *ads, const char *mod_dn, ADS_MODLIST mods) **/ ADS_STATUS ads_gen_add(ADS_STRUCT *ads, const char *new_dn, ADS_MODLIST mods) { - int ret, i; - char *utf8_dn = NULL; + int i; - push_utf8_allocate((void **) &utf8_dn, new_dn); - /* find the end of the list, marked by NULL or -1 */ for(i=0;(mods[i]!=0)&&(mods[i]!=(LDAPMod *) -1);i++); /* make sure the end of the list is NULL */ mods[i] = NULL; - ret = ldap_add_s(ads->ld, utf8_dn ? utf8_dn : new_dn, mods); - SAFE_FREE(utf8_dn); - return ADS_ERROR(ret); + return ADS_ERROR(ldap_add_s(ads->ld, new_dn, mods)); } /** @@ -759,11 +737,7 @@ ADS_STATUS ads_gen_add(ADS_STRUCT *ads, const char *new_dn, ADS_MODLIST mods) **/ ADS_STATUS ads_del_dn(ADS_STRUCT *ads, char *del_dn) { - int ret; - char *utf8_dn = NULL; - push_utf8_allocate((void **) &utf8_dn, del_dn); - ret = ldap_delete(ads->ld, utf8_dn ? utf8_dn : del_dn); - return ADS_ERROR(ret); + return ADS_ERROR(ldap_delete(ads->ld, del_dn)); } /** @@ -795,8 +769,6 @@ static ADS_STATUS ads_add_machine_acct(ADS_STRUCT *ads, const char *hostname, char *ou_str; TALLOC_CTX *ctx; ADS_MODLIST mods; - const char *objectClass[] = {"top", "person", "organizationalPerson", - "user", "computer", NULL}; if (!(ctx = talloc_init_named("machine_account"))) return ADS_ERROR(LDAP_NO_MEMORY); @@ -824,15 +796,17 @@ static ADS_STATUS ads_add_machine_acct(ADS_STRUCT *ads, const char *hostname, if (!(mods = ads_init_mods(ctx))) goto done; - ads_mod_str(ctx, &mods, "cn", hostname); - ads_mod_str(ctx, &mods, "sAMAccountName", samAccountName); - ads_mod_strlist(ctx, &mods, "objectClass", objectClass); - ads_mod_str(ctx, &mods, "userPrincipalName", host_upn); - ads_mod_str(ctx, &mods, "servicePrincipalName", host_spn); - ads_mod_str(ctx, &mods, "dNSHostName", hostname); - ads_mod_str(ctx, &mods, "userAccountControl", controlstr); - ads_mod_str(ctx, &mods, "operatingSystem", "Samba"); - ads_mod_str(ctx, &mods, "operatingSystemVersion", VERSION); + ads_mod_add(ctx, &mods, "cn", hostname); + ads_mod_add(ctx, &mods, "sAMAccountName", samAccountName); + ads_mod_add_var(ctx, &mods, LDAP_MOD_ADD, "objectClass", + "top", "person", "organizationalPerson", + "user", "computer", NULL); + ads_mod_add(ctx, &mods, "userPrincipalName", host_upn); + ads_mod_add(ctx, &mods, "servicePrincipalName", host_spn); + ads_mod_add(ctx, &mods, "dNSHostName", hostname); + ads_mod_add(ctx, &mods, "userAccountControl", controlstr); + ads_mod_add(ctx, &mods, "operatingSystem", "Samba"); + ads_mod_add(ctx, &mods, "operatingSystemVersion", VERSION); ads_gen_add(ads, new_dn, mods); ret = ads_set_machine_sd(ads, hostname, new_dn); @@ -903,11 +877,11 @@ static void dump_sd(const char *filed, struct berval **values) /* dump a string result from ldap */ -static void dump_string(const char *field, char **values) +static void dump_string(const char *field, struct berval **values) { int i; for (i=0; values[i]; i++) { - printf("%s: %s\n", field, values[i]); + printf("%s: %s\n", field, values[i]->bv_val); } } @@ -916,39 +890,33 @@ static void dump_string(const char *field, char **values) used for debugging */ -static BOOL ads_dump_field(char *field, void **values, void *data_area) +static void ads_dump_field(char *field, void **values, void *data_area) { struct { char *name; - BOOL string; void (*handler)(const char *, struct berval **); } handlers[] = { - {"objectGUID", False, dump_binary}, - {"nTSecurityDescriptor", False, dump_sd}, - {"objectSid", False, dump_sid}, - {NULL, True, NULL} + {"objectGUID", dump_binary}, + {"nTSecurityDescriptor", dump_sd}, + {"objectSid", dump_sid}, + {NULL, NULL} }; int i; if (!field) { /* must be end of an entry */ printf("\n"); - return False; + return; } for (i=0; handlers[i].name; i++) { if (StrCaseCmp(handlers[i].name, field) == 0) { - if (!values) /* first time, indicate string or not */ - return handlers[i].string; handlers[i].handler(field, (struct berval **) values); break; } } if (!handlers[i].name) { - if (!values) /* first time, indicate string conversion */ - return True; - dump_string(field, (char **)values); + dump_string(field, (struct berval **) values); } - return False; } /** @@ -975,58 +943,63 @@ void ads_dump(ADS_STRUCT *ads, void *res) * @param data_area user-defined area to pass to function **/ void ads_process_results(ADS_STRUCT *ads, void *res, - BOOL(*fn)(char *, void **, void *), + void(*fn)(char *, void **, void *), void *data_area) { void *msg; - TALLOC_CTX *ctx; - - if (!(ctx = talloc_init())) - return; for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) { - char *utf8_field; + char *field; BerElement *b; - for (utf8_field=ldap_first_attribute(ads->ld, - (LDAPMessage *)msg,&b); - utf8_field; - utf8_field=ldap_next_attribute(ads->ld, - (LDAPMessage *)msg,b)) { - struct berval **ber_vals; - char **str_vals, **utf8_vals; - char *field; - BOOL string; - - pull_utf8_talloc(ctx, (void **) &field, utf8_field); - string = fn(field, NULL, data_area); - - if (string) { - utf8_vals = ldap_get_values(ads->ld, - (LDAPMessage *)msg, field); - str_vals = ads_pull_strvals(ctx, - (const char **) utf8_vals); - fn(field, (void **) str_vals, data_area); - ldap_value_free(utf8_vals); - } else { - ber_vals = ldap_get_values_len(ads->ld, - (LDAPMessage *)msg, field); - fn(field, (void **) ber_vals, data_area); - - ldap_value_free_len(ber_vals); - } - ldap_memfree(utf8_field); + for (field = ldap_first_attribute(ads->ld, (LDAPMessage *)msg, &b); + field; + field = ldap_next_attribute(ads->ld, (LDAPMessage *)msg, b)) { + struct berval **values; + + values = ldap_get_values_len(ads->ld, (LDAPMessage *)msg, field); + fn(field, (void **) values, data_area); + + ldap_value_free_len(values); + ldap_memfree(field); } ber_free(b, 0); - talloc_destroy_pool(ctx); fn(NULL, NULL, data_area); /* completed an entry */ } - talloc_destroy(ctx); } /** + * Walk through an entry, calling a function for each attribute found. + * The function receives a field name, a berval * array of values, + * and a data area passed through from the start. + * @param ads connection to ads server + * @param res Results to process + * @param fn Function for processing each result + * @param data_area user-defined area to pass to function + **/ +void ads_process_entry(ADS_STRUCT *ads, void *msg, + void(*fn)(ADS_STRUCT *, char *, void **, void *), + void *data_area) +{ + char *field; + BerElement *b; + + for (field = ldap_first_attribute(ads->ld, (LDAPMessage *)msg, &b); + field; + field = ldap_next_attribute(ads->ld, (LDAPMessage *)msg, b)) { + struct berval **values; + + values = ldap_get_values_len(ads->ld, (LDAPMessage *)msg, field); + fn(ads, field, (void **) values, data_area); + + ldap_value_free_len(values); + ldap_memfree(field); + } + ber_free(b, 0); +} +/** * count how many replies are in a LDAPMessage * @param ads connection to ads server * @param res Results to count @@ -1137,7 +1110,6 @@ ADS_STATUS ads_set_machine_sd(ADS_STRUCT *ads, const char *hostname, char *dn) char *exp = 0; size_t sd_size = 0; struct berval **bvals = 0; - struct berval bval = {0, NULL}; prs_struct ps; prs_struct ps_wire; @@ -1192,9 +1164,7 @@ ADS_STATUS ads_set_machine_sd(ADS_STRUCT *ads, const char *hostname, char *dn) #endif if (!(mods = ads_init_mods(ctx))) return ADS_ERROR(LDAP_NO_MEMORY); - bval.bv_len = sd_size; - bval.bv_val = prs_data_p(&ps_wire); - ads_mod_ber(ctx, &mods, attrs[0], &bval); + ads_mod_repl_len(ctx, &mods, attrs[0], sd_size, ps_wire.data_p); ret = ads_gen_mod(ads, dn, mods); prs_mem_free(&ps); @@ -1231,11 +1201,7 @@ ADS_STATUS ads_set_machine_password(ADS_STRUCT *ads, strlower(host); - /* - we need to use the '$' form of the name here, as otherwise the - server might end up setting the password for a user instead - */ - asprintf(&principal, "%s$@%s", host, ads->realm); + asprintf(&principal, "%s@%s", host, ads->realm); status = krb5_set_password(ads->kdc_server, principal, password); @@ -1280,59 +1246,18 @@ char *ads_pull_string(ADS_STRUCT *ads, { char **values; char *ret = NULL; - char *ux_string; - int rc; values = ldap_get_values(ads->ld, msg, field); if (!values) return NULL; if (values[0]) { - rc = pull_utf8_talloc(mem_ctx, (void **)&ux_string, - values[0]); - if (rc != -1) - ret = ux_string; - + ret = talloc_strdup(mem_ctx, values[0]); } ldap_value_free(values); return ret; } /** - * pull an array of strings from a ADS result - * @param ads connection to ads server - * @param mem_ctx TALLOC_CTX to use for allocating result string - * @param msg Results of search - * @param field Attribute to retrieve - * @return Result strings in talloc context - **/ -char **ads_pull_strings(ADS_STRUCT *ads, - TALLOC_CTX *mem_ctx, void *msg, const char *field) -{ - char **values; - char **ret = NULL; - int i, n; - - values = ldap_get_values(ads->ld, msg, field); - if (!values) return NULL; - - for (i=0;values[i];i++) /* noop */ ; - n = i; - - ret = talloc(mem_ctx, sizeof(char *) * (n+1)); - - for (i=0;i<n;i++) { - if (pull_utf8_talloc(mem_ctx, (void **)&ret[i], values[i]) == -1) { - return NULL; - } - } - ret[i] = NULL; - - ldap_value_free(values); - return ret; -} - - -/** * pull a single uint32 from a ADS result * @param ads connection to ads server * @param msg Results of search |