diff options
author | Andrew Tridgell <tridge@samba.org> | 2002-07-15 10:35:28 +0000 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 2002-07-15 10:35:28 +0000 |
commit | e90b65284812aaa5ff9e9935ce9bbad7791cbbcd (patch) | |
tree | 9e744d1dc2f93934a4b49166a37383d3cb2b2139 /source3/libads | |
parent | ec167dc9cc0ec2ee461837c25a371d2981744208 (diff) | |
download | samba-e90b65284812aaa5ff9e9935ce9bbad7791cbbcd.tar.gz samba-e90b65284812aaa5ff9e9935ce9bbad7791cbbcd.tar.bz2 samba-e90b65284812aaa5ff9e9935ce9bbad7791cbbcd.zip |
updated the 3.0 branch from the head branch - ready for alpha18
(This used to be commit 03ac082dcb375b6f3ca3d810a6a6367542bc23ce)
Diffstat (limited to 'source3/libads')
-rw-r--r-- | source3/libads/ads_struct.c | 28 | ||||
-rw-r--r-- | source3/libads/disp_sec.c | 20 | ||||
-rw-r--r-- | source3/libads/kerberos.c | 155 | ||||
-rw-r--r-- | source3/libads/ldap.c | 679 | ||||
-rw-r--r-- | source3/libads/ldap_printer.c | 73 | ||||
-rw-r--r-- | source3/libads/ldap_user.c | 52 | ||||
-rw-r--r-- | source3/libads/sasl.c | 3 |
7 files changed, 510 insertions, 500 deletions
diff --git a/source3/libads/ads_struct.c b/source3/libads/ads_struct.c index 489f301ae2..638dc0b22e 100644 --- a/source3/libads/ads_struct.c +++ b/source3/libads/ads_struct.c @@ -81,7 +81,8 @@ static char *find_ldap_server(ADS_STRUCT *ads) char *list = NULL; struct in_addr ip; - if (ads->realm && + if (ads->realm && + strcasecmp(ads->workgroup, lp_workgroup()) == 0 && ldap_domain2hostlist(ads->realm, &list) == LDAP_SUCCESS) { char *p; p = strchr(list, ':'); @@ -90,7 +91,12 @@ static char *find_ldap_server(ADS_STRUCT *ads) } /* get desperate, find the domain controller IP */ - if (resolve_name(lp_workgroup(), &ip, 0x1B)) { + if (resolve_name(ads->workgroup, &ip, 0x1B)) { + return strdup(inet_ntoa(ip)); + } + + /* or a BDC ... */ + if (resolve_name(ads->workgroup, &ip, 0x1C)) { return strdup(inet_ntoa(ip)); } @@ -115,6 +121,7 @@ static char *find_ldap_server(ADS_STRUCT *ads) initialise a ADS_STRUCT, ready for some ads_ ops */ ADS_STRUCT *ads_init(const char *realm, + const char *workgroup, const char *ldap_server, const char *bind_path, const char *password) @@ -124,7 +131,12 @@ ADS_STRUCT *ads_init(const char *realm, ads = (ADS_STRUCT *)smb_xmalloc(sizeof(*ads)); ZERO_STRUCTP(ads); + if (!workgroup) { + workgroup = lp_workgroup(); + } + ads->realm = realm? strdup(realm) : NULL; + ads->workgroup = strdup(workgroup); ads->ldap_server = ldap_server? strdup(ldap_server) : NULL; ads->bind_path = bind_path? strdup(bind_path) : NULL; ads->ldap_port = LDAP_PORT; @@ -140,8 +152,10 @@ ADS_STRUCT *ads_init(const char *realm, ads->bind_path = ads_build_dn(ads->realm); } if (!ads->ldap_server) { - ads->ldap_server = strdup(lp_ads_server()); - if (!ads->ldap_server[0]) { + if (strcasecmp(ads->workgroup, lp_workgroup()) == 0) { + ads->ldap_server = strdup(lp_ads_server()); + } + if (!ads->ldap_server || !ads->ldap_server[0]) { ads->ldap_server = find_ldap_server(ads); } } @@ -153,6 +167,12 @@ ADS_STRUCT *ads_init(const char *realm, return ads; } +/* a simpler ads_init() interface using all defaults */ +ADS_STRUCT *ads_init_simple(void) +{ + return ads_init(NULL, NULL, NULL, NULL, NULL); +} + /* free the memory used by the ADS structure initialized with 'ads_init(...)' */ diff --git a/source3/libads/disp_sec.c b/source3/libads/disp_sec.c index ab8ceecb0c..a930fd6fe0 100644 --- a/source3/libads/disp_sec.c +++ b/source3/libads/disp_sec.c @@ -52,7 +52,7 @@ static struct perm_mask_str { }; /* convert a security permissions into a string */ -void ads_disp_perms(uint32 type) +static void ads_disp_perms(uint32 type) { int i = 0; int j = 0; @@ -82,20 +82,8 @@ void ads_disp_perms(uint32 type) puts(""); } -/* Check if ACE has OBJECT type */ -BOOL ads_ace_object(uint8 type) -{ - if (type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT || - type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT || - type == SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT || - type == SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT) { - return True; - } - return False; -} - /* display ACE */ -void ads_disp_ace(SEC_ACE *sec_ace) +static void ads_disp_ace(SEC_ACE *sec_ace) { char *access_type = "UNKNOWN"; @@ -123,7 +111,7 @@ void ads_disp_ace(SEC_ACE *sec_ace) } else if (sec_ace->type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT) { access_type = "ALLOWED OBJECT"; } else if (sec_ace->type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT) { - access_type = "DEINED OBJECT"; + access_type = "DENIED OBJECT"; } else if (sec_ace->type == SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT) { access_type = "AUDIT OBJECT"; } @@ -135,7 +123,7 @@ void ads_disp_ace(SEC_ACE *sec_ace) } /* display ACL */ -void ads_disp_acl(SEC_ACL *sec_acl, char *type) +static void ads_disp_acl(SEC_ACL *sec_acl, char *type) { if (!sec_acl) printf("------- (%s) ACL not present\n", type); diff --git a/source3/libads/kerberos.c b/source3/libads/kerberos.c index 194a71275e..1ba5d978e8 100644 --- a/source3/libads/kerberos.c +++ b/source3/libads/kerberos.c @@ -25,6 +25,28 @@ #ifdef HAVE_KRB5 /* + we use a prompter to avoid a crash bug in the kerberos libs when + dealing with empty passwords + this prompter is just a string copy ... +*/ +static krb5_error_code +kerb_prompter(krb5_context ctx, void *data, + const char *name, + const char *banner, + int num_prompts, + krb5_prompt prompts[]) +{ + if (num_prompts == 0) return 0; + + memset(prompts[0].reply->data, 0, prompts[0].reply->length); + if (prompts[0].reply->length > 0) { + strncpy(prompts[0].reply->data, data, prompts[0].reply->length-1); + prompts[0].reply->length = strlen(prompts[0].reply->data); + } + return 0; +} + +/* simulate a kinit, putting the tgt in the default cache location remus@snapserver.com */ @@ -36,11 +58,6 @@ int kerberos_kinit_password(const char *principal, const char *password) krb5_principal me; krb5_creds my_creds; - if (! *password) { - /* kerberos dies on an empty password! */ - return KRB5_PARSE_MALFORMED; - } - if ((code = krb5_init_context(&ctx))) return code; @@ -54,8 +71,9 @@ int kerberos_kinit_password(const char *principal, const char *password) return code; } - if ((code = krb5_get_init_creds_password(ctx, &my_creds, me, (char*)password, NULL, - NULL, 0, NULL, NULL))) { + if ((code = krb5_get_init_creds_password(ctx, &my_creds, me, NULL, + kerb_prompter, + password, 0, NULL, NULL))) { krb5_free_principal(ctx, me); krb5_free_context(ctx); return code; @@ -111,128 +129,5 @@ int ads_kinit_password(ADS_STRUCT *ads) return ret; } -/* - verify an incoming ticket and parse out the principal name and - authorization_data if available -*/ -NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket, - char **principal, DATA_BLOB *auth_data) -{ - krb5_context context; - krb5_auth_context auth_context = NULL; - krb5_keytab keytab = NULL; - krb5_data packet; - krb5_ticket *tkt = NULL; - krb5_data salt; - krb5_encrypt_block eblock; - int ret; - krb5_keyblock * key; - krb5_principal host_princ; - char *host_princ_s; - extern pstring global_myname; - fstring myname; - char *password_s; - krb5_data password; - - if (!secrets_init()) { - DEBUG(1,("secrets_init failed\n")); - return NT_STATUS_LOGON_FAILURE; - } - - password_s = secrets_fetch_machine_password(); - if (!password_s) { - DEBUG(1,("failed to fetch machine password\n")); - return NT_STATUS_LOGON_FAILURE; - } - - password.data = password_s; - password.length = strlen(password_s); - - ret = krb5_init_context(&context); - if (ret) { - DEBUG(1,("krb5_init_context failed (%s)\n", error_message(ret))); - return NT_STATUS_LOGON_FAILURE; - } - - ret = krb5_set_default_realm(context, ads->realm); - if (ret) { - DEBUG(1,("krb5_set_default_realm failed (%s)\n", error_message(ret))); - ads_destroy(&ads); - return NT_STATUS_LOGON_FAILURE; - } - - /* this whole process is far more complex than I would - like. We have to go through all this to allow us to store - the secret internally, instead of using /etc/krb5.keytab */ - ret = krb5_auth_con_init(context, &auth_context); - if (ret) { - DEBUG(1,("krb5_auth_con_init failed (%s)\n", error_message(ret))); - return NT_STATUS_LOGON_FAILURE; - } - - fstrcpy(myname, global_myname); - strlower(myname); - asprintf(&host_princ_s, "HOST/%s@%s", myname, lp_realm()); - ret = krb5_parse_name(context, host_princ_s, &host_princ); - if (ret) { - DEBUG(1,("krb5_parse_name(%s) failed (%s)\n", host_princ_s, error_message(ret))); - return NT_STATUS_LOGON_FAILURE; - } - - ret = krb5_principal2salt(context, host_princ, &salt); - if (ret) { - DEBUG(1,("krb5_principal2salt failed (%s)\n", error_message(ret))); - return NT_STATUS_LOGON_FAILURE; - } - - if (!(key = (krb5_keyblock *)malloc(sizeof(*key)))) { - return NT_STATUS_NO_MEMORY; - } - - krb5_use_enctype(context, &eblock, ENCTYPE_DES_CBC_MD5); - - ret = krb5_string_to_key(context, &eblock, key, &password, &salt); - if (ret) { - DEBUG(1,("krb5_string_to_key failed (%s)\n", error_message(ret))); - return NT_STATUS_LOGON_FAILURE; - } - - krb5_auth_con_setuseruserkey(context, auth_context, key); - - packet.length = ticket->length; - packet.data = (krb5_pointer)ticket->data; - -#if 0 - file_save("/tmp/ticket.dat", ticket->data, ticket->length); -#endif - - if ((ret = krb5_rd_req(context, &auth_context, &packet, - NULL, keytab, NULL, &tkt))) { - DEBUG(3,("krb5_rd_req with auth failed (%s)\n", - error_message(ret))); - return NT_STATUS_LOGON_FAILURE; - } - - if (tkt->enc_part2) { - *auth_data = data_blob(tkt->enc_part2->authorization_data[0]->contents, - tkt->enc_part2->authorization_data[0]->length); - } - -#if 0 - if (tkt->enc_part2) { - file_save("/tmp/authdata.dat", - tkt->enc_part2->authorization_data[0]->contents, - tkt->enc_part2->authorization_data[0]->length); - } -#endif - - if ((ret = krb5_unparse_name(context, tkt->enc_part2->client, principal))) { - DEBUG(3,("krb5_unparse_name failed (%s)\n", - error_message(ret))); - return NT_STATUS_LOGON_FAILURE; - } - - return NT_STATUS_OK; -} #endif diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c index e2e351bd4b..9d15c4e33c 100644 --- a/source3/libads/ldap.c +++ b/source3/libads/ldap.c @@ -30,6 +30,11 @@ * * 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 **/ /** @@ -45,10 +50,38 @@ ADS_STATUS ads_connect(ADS_STRUCT *ads) ads->last_attempt = time(NULL); - ads->ld = ldap_open(ads->ldap_server, ads->ldap_port); + 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); + } + } + 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")); @@ -76,6 +109,81 @@ 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 @@ -84,8 +192,8 @@ ADS_STATUS ads_connect(ADS_STRUCT *ads) * @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 - * @param attrs Attributes to retrieve + * @param exp Search expression - specified in local charset + * @param attrs Attributes to retrieve - specified in utf8 or ascii * @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 @@ -96,25 +204,46 @@ ADS_STATUS ads_do_paged_search(ADS_STRUCT *ads, const char *bind_path, const char **attrs, void **res, int *count, void **cookie) { - int rc; - int version; - LDAPControl PagedResults; - LDAPControl NoReferrals; + int rc, i, version; + char *utf8_exp, *utf8_path, **search_attrs; + LDAPControl PagedResults, NoReferrals, *controls[3], **rcontrols; BerElement *cookie_be = NULL; struct berval *cookie_bv= NULL; - LDAPControl *controls[3]; - LDAPControl **rcontrols; - int i; + TALLOC_CTX *ctx; *res = NULL; - ldap_get_option(ads->ld, LDAP_OPT_PROTOCOL_VERSION, &version); + if (!(ctx = talloc_init())) + return ADS_ERROR(LDAP_NO_MEMORY); - /* 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); + /* 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; + } cookie_be = ber_alloc_t(LBER_USE_DER); if (cookie && *cookie) { @@ -143,33 +272,32 @@ 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 - seem to handle them correctly. They result in the result - record containing the server control being removed from the - result list (tridge) + 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) 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, bind_path, scope, exp, - (char **) attrs, 0, controls, NULL, - NULL, LDAP_NO_LIMIT, - (LDAPMessage **)res); + rc = ldap_search_ext_s(ads->ld, utf8_path, scope, utf8_exp, + search_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))); - return ADS_ERROR(rc); + goto done; } rc = ldap_parse_result(ads->ld, *res, NULL, NULL, NULL, NULL, &rcontrols, 0); if (!rcontrols) { - return ADS_ERROR(rc); + goto done; } for (i=0; rcontrols[i]; i++) { @@ -189,7 +317,12 @@ 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); } @@ -234,7 +367,6 @@ 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 */ } @@ -248,15 +380,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 - * @param attrs Attributes to retrieve + * @param exp Search expression - specified in local charset + * @param attrs Attributes to retrieve - specified in UTF-8 or ascii * @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, - void(*fn)(char *, void **, void *), + BOOL(*fn)(char *, void **, void *), void *data_area) { void *cookie = NULL; @@ -301,14 +433,42 @@ 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; - rc = ldap_search_ext_s(ads->ld, - bind_path, scope, - exp, (char **) attrs, 0, NULL, 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, &timeout, LDAP_NO_LIMIT, (LDAPMessage **)res); if (rc == LDAP_SIZELIMIT_EXCEEDED) { @@ -316,6 +476,10 @@ 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); } /** @@ -367,8 +531,7 @@ void ads_msgfree(ADS_STRUCT *ads, void *msg) **/ void ads_memfree(ADS_STRUCT *ads, void *mem) { - if (!mem) return; - ldap_memfree(mem); + SAFE_FREE(mem); } /** @@ -379,7 +542,12 @@ void ads_memfree(ADS_STRUCT *ads, void *mem) **/ char *ads_get_dn(ADS_STRUCT *ads, void *res) { - return ldap_get_dn(ads->ld, 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; } /** @@ -403,25 +571,6 @@ 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 @@ -441,14 +590,29 @@ 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, char **values) + int mod_op, const char *name, + const void **invals) { 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; @@ -465,217 +629,66 @@ 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 = name; + modlist[curmod]->mod_type = talloc_strdup(ctx, name); if (mod_op & LDAP_MOD_BVALUES) modlist[curmod]->mod_bvalues = (struct berval **) values; else - modlist[curmod]->mod_values = values; + modlist[curmod]->mod_values = (char **) values; modlist[curmod]->mod_op = mod_op; return ADS_ERROR(LDAP_SUCCESS); } /** - * Add an already-constructed list of values to a mod list for an ADD + * Add a single string value to a mod list * @param ctx An initialized TALLOC_CTX * @param mods An initialized ADS_MODLIST * @param name The attribute name to add - * @param values Constructed values list to add + * @param val The value to add - NULL means DELETE * @return ADS STATUS indicating success of add **/ -ADS_STATUS ads_mod_add_list(TALLOC_CTX *ctx, ADS_MODLIST *mods, - char *name, char **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 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 values Constructed values list to add - * @return ADS STATUS indicating success of add - **/ -ADS_STATUS ads_mod_repl_list(TALLOC_CTX *ctx, ADS_MODLIST *mods, - char *name, char **values) +ADS_STATUS ads_mod_str(TALLOC_CTX *ctx, ADS_MODLIST *mods, + const char *name, const char *val) { - 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 + 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); } /** - * 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 + * Add an array of string values to a mod list * @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 (struct berval *) form + * @param vals The array of string values to add - NULL means DELETE * @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, ...) +ADS_STATUS ads_mod_strlist(TALLOC_CTX *ctx, ADS_MODLIST *mods, + const char *name, const char **vals) { - 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); + if (!vals) + 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 berval value to a mod list - for ADD + * Add a single ber-encoded value to a mod list * @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 + * @param val The value to add - NULL means DELETE * @return ADS STATUS indicating success of add **/ -ADS_STATUS ads_mod_repl_len(TALLOC_CTX *ctx, ADS_MODLIST *mods, - const char *name, size_t size, char *val) +static ADS_STATUS ads_mod_ber(TALLOC_CTX *ctx, ADS_MODLIST *mods, + const char *name, const struct berval *val) { - struct berval *bval = NULL; - - if (!(bval = talloc_zero(ctx, sizeof(struct berval *)))) - return ADS_ERROR(LDAP_NO_MEMORY); - + const struct berval *values[2] = {val, NULL}; if (!val) - 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); - } + 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); } /** @@ -688,6 +701,7 @@ ADS_STATUS ads_mod_repl_len(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 @@ -701,12 +715,15 @@ 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, mod_dn, (LDAPMod **) mods, - controls, NULL); + ret = ldap_modify_ext_s(ads->ld, utf8_dn ? utf8_dn : mod_dn, + (LDAPMod **) mods, controls, NULL); + SAFE_FREE(utf8_dn); return ADS_ERROR(ret); } @@ -719,14 +736,19 @@ 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 i; + int ret, i; + char *utf8_dn = NULL; + 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; - return ADS_ERROR(ldap_add_s(ads->ld, new_dn, mods)); + ret = ldap_add_s(ads->ld, utf8_dn ? utf8_dn : new_dn, mods); + SAFE_FREE(utf8_dn); + return ADS_ERROR(ret); } /** @@ -737,7 +759,11 @@ 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) { - return ADS_ERROR(ldap_delete(ads->ld, 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); } /** @@ -769,6 +795,8 @@ 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); @@ -796,17 +824,15 @@ static ADS_STATUS ads_add_machine_acct(ADS_STRUCT *ads, const char *hostname, if (!(mods = ads_init_mods(ctx))) goto done; - 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_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_gen_add(ads, new_dn, mods); ret = ads_set_machine_sd(ads, hostname, new_dn); @@ -877,11 +903,11 @@ static void dump_sd(const char *filed, struct berval **values) /* dump a string result from ldap */ -static void dump_string(const char *field, struct berval **values) +static void dump_string(const char *field, char **values) { int i; for (i=0; values[i]; i++) { - printf("%s: %s\n", field, values[i]->bv_val); + printf("%s: %s\n", field, values[i]); } } @@ -890,33 +916,39 @@ static void dump_string(const char *field, struct berval **values) used for debugging */ -static void ads_dump_field(char *field, void **values, void *data_area) +static BOOL ads_dump_field(char *field, void **values, void *data_area) { struct { char *name; + BOOL string; void (*handler)(const char *, struct berval **); } handlers[] = { - {"objectGUID", dump_binary}, - {"nTSecurityDescriptor", dump_sd}, - {"objectSid", dump_sid}, - {NULL, NULL} + {"objectGUID", False, dump_binary}, + {"nTSecurityDescriptor", False, dump_sd}, + {"objectSid", False, dump_sid}, + {NULL, True, NULL} }; int i; if (!field) { /* must be end of an entry */ printf("\n"); - return; + return False; } 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) { - dump_string(field, (struct berval **) values); + if (!values) /* first time, indicate string conversion */ + return True; + dump_string(field, (char **)values); } + return False; } /** @@ -943,63 +975,58 @@ 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, - void(*fn)(char *, void **, void *), + BOOL(*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 *field; + char *utf8_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(field, (void **) values, data_area); - - ldap_value_free_len(values); - ldap_memfree(field); + 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); } 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 @@ -1110,6 +1137,7 @@ 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; @@ -1164,7 +1192,9 @@ 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); - ads_mod_repl_len(ctx, &mods, attrs[0], sd_size, ps_wire.data_p); + bval.bv_len = sd_size; + bval.bv_val = prs_data_p(&ps_wire); + ads_mod_ber(ctx, &mods, attrs[0], &bval); ret = ads_gen_mod(ads, dn, mods); prs_mem_free(&ps); @@ -1201,7 +1231,11 @@ ADS_STATUS ads_set_machine_password(ADS_STRUCT *ads, strlower(host); - asprintf(&principal, "%s@%s", host, ads->realm); + /* + 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); status = krb5_set_password(ads->kdc_server, principal, password); @@ -1246,18 +1280,59 @@ 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]) { - ret = talloc_strdup(mem_ctx, values[0]); + rc = pull_utf8_talloc(mem_ctx, (void **)&ux_string, + values[0]); + if (rc != -1) + ret = ux_string; + } 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 diff --git a/source3/libads/ldap_printer.c b/source3/libads/ldap_printer.c index 52771ba39a..64ae8252c8 100644 --- a/source3/libads/ldap_printer.c +++ b/source3/libads/ldap_printer.c @@ -31,7 +31,7 @@ ADS_STATUS ads_find_printer_on_server(ADS_STRUCT *ads, void **res, char *printer, char *servername) { ADS_STATUS status; - char *srv_dn, *exp; + char *srv_dn, **srv_cn, *exp; const char *attrs[] = {"*", "nTSecurityDescriptor", NULL}; status = ads_find_machine_acct(ads, res, servername); @@ -41,12 +41,14 @@ ADS_STATUS ads_find_printer_on_server(ADS_STRUCT *ads, void **res, return status; } srv_dn = ldap_get_dn(ads->ld, *res); + srv_cn = ldap_explode_dn(srv_dn, 1); ads_msgfree(ads, *res); - asprintf(&exp, "(printerName=%s)", printer); - status = ads_do_search(ads, srv_dn, LDAP_SCOPE_SUBTREE, - exp, attrs, res); + asprintf(&exp, "(cn=%s-%s)", srv_cn[0], printer); + status = ads_search(ads, res, exp, attrs); + ldap_memfree(srv_dn); + ldap_value_free(srv_cn); free(exp); return status; } @@ -68,33 +70,33 @@ ADS_STATUS ads_mod_printer_entry(ADS_STRUCT *ads, char *prt_dn, mods = ads_init_mods(ctx); /* add the attributes to the list - required ones first */ - ads_mod_repl(ctx, &mods, "printerName", prt->printerName); - ads_mod_repl(ctx, &mods, "serverName", prt->serverName); - ads_mod_repl(ctx, &mods, "shortServerName", prt->shortServerName); - ads_mod_repl(ctx, &mods, "uNCName", prt->uNCName); - ads_mod_repl(ctx, &mods, "versionNumber", prt->versionNumber); + ads_mod_str(ctx, &mods, "printerName", prt->printerName); + ads_mod_str(ctx, &mods, "serverName", prt->serverName); + ads_mod_str(ctx, &mods, "shortServerName", prt->shortServerName); + ads_mod_str(ctx, &mods, "uNCName", prt->uNCName); + ads_mod_str(ctx, &mods, "versionNumber", prt->versionNumber); /* now the optional ones */ - ads_mod_repl_list(ctx, &mods, "description", prt->description); - ads_mod_repl(ctx, &mods, "assetNumber",prt->assetNumber); - ads_mod_repl(ctx, &mods, "bytesPerMinute",prt->bytesPerMinute); - ads_mod_repl(ctx, &mods, "defaultPriority",prt->defaultPriority); - ads_mod_repl(ctx, &mods, "driverName", prt->driverName); - ads_mod_repl(ctx, &mods, "driverVersion",prt->driverVersion); - ads_mod_repl(ctx, &mods, "location", prt->location); - ads_mod_repl(ctx, &mods, "operatingSystem",prt->operatingSystem); - ads_mod_repl(ctx, &mods, "operatingSystemHotfix", + ads_mod_strlist(ctx, &mods, "description", prt->description); + ads_mod_str(ctx, &mods, "assetNumber",prt->assetNumber); + ads_mod_str(ctx, &mods, "bytesPerMinute",prt->bytesPerMinute); + ads_mod_str(ctx, &mods, "defaultPriority",prt->defaultPriority); + ads_mod_str(ctx, &mods, "driverName", prt->driverName); + ads_mod_str(ctx, &mods, "driverVersion",prt->driverVersion); + ads_mod_str(ctx, &mods, "location", prt->location); + ads_mod_str(ctx, &mods, "operatingSystem",prt->operatingSystem); + ads_mod_str(ctx, &mods, "operatingSystemHotfix", prt->operatingSystemHotfix); - ads_mod_repl(ctx, &mods, "operatingSystemServicePack", + ads_mod_str(ctx, &mods, "operatingSystemServicePack", prt->operatingSystemServicePack); - ads_mod_repl(ctx, &mods, "operatingSystemVersion", + ads_mod_str(ctx, &mods, "operatingSystemVersion", prt->operatingSystemVersion); - ads_mod_repl(ctx, &mods, "physicalLocationObject", + ads_mod_str(ctx, &mods, "physicalLocationObject", prt->physicalLocationObject); - ads_mod_repl_list(ctx, &mods, "portName", prt->portName); - ads_mod_repl(ctx, &mods, "printStartTime", prt->printStartTime); - ads_mod_repl(ctx, &mods, "printEndTime", prt->printEndTime); - ads_mod_repl_list(ctx, &mods, "printBinNames", prt->printBinNames); + ads_mod_strlist(ctx, &mods, "portName", prt->portName); + ads_mod_str(ctx, &mods, "printStartTime", prt->printStartTime); + ads_mod_str(ctx, &mods, "printEndTime", prt->printEndTime); + ads_mod_strlist(ctx, &mods, "printBinNames", prt->printBinNames); /*... and many others */ /* do the ldap modify */ @@ -124,12 +126,12 @@ static ADS_STATUS ads_add_printer_entry(ADS_STRUCT *ads, char *prt_dn, return ADS_ERROR(LDAP_NO_MEMORY); /* These are the fields a printQueue must contain */ - ads_mod_add(ctx, &mods, "uNCName", prt->uNCName); - ads_mod_add(ctx, &mods, "versionNumber", prt->versionNumber); - ads_mod_add(ctx, &mods, "serverName", prt->serverName); - ads_mod_add(ctx, &mods, "shortServerName", prt->shortServerName); - ads_mod_add(ctx, &mods, "printerName", prt->printerName); - ads_mod_add(ctx, &mods, "objectClass", "printQueue"); + ads_mod_str(ctx, &mods, "uNCName", prt->uNCName); + ads_mod_str(ctx, &mods, "versionNumber", prt->versionNumber); + ads_mod_str(ctx, &mods, "serverName", prt->serverName); + ads_mod_str(ctx, &mods, "shortServerName", prt->shortServerName); + ads_mod_str(ctx, &mods, "printerName", prt->printerName); + ads_mod_str(ctx, &mods, "objectClass", "printQueue"); status = ads_gen_add(ads, prt_dn, mods); @@ -157,14 +159,11 @@ ADS_STATUS ads_add_printer(ADS_STRUCT *ads, const ADS_PRINTER_ENTRY *prt) prt->shortServerName)); return status; } - host_dn = ldap_get_dn(ads->ld, res); + host_dn = ads_get_dn(ads, res); ads_msgfree(ads, res); - /* printer dn is cn=server-printer followed by host dn */ - asprintf(&prt_dn, "cn=%s-%s,%s", prt->shortServerName, - prt->printerName, host_dn); - - status = ads_search_dn(ads, &res, prt_dn, attrs); + ads_find_printer_on_server(ads, &res, prt->printerName, + prt->shortServerName); if (ADS_ERR_OK(status) && ads_count_replies(ads, res)) { DEBUG(1, ("ads_add_printer: printer %s already exists\n", diff --git a/source3/libads/ldap_user.c b/source3/libads/ldap_user.c index 13e68eb82e..b6e3d189c5 100644 --- a/source3/libads/ldap_user.c +++ b/source3/libads/ldap_user.c @@ -43,7 +43,9 @@ ADS_STATUS ads_add_user_acct(ADS_STRUCT *ads, const char *user, TALLOC_CTX *ctx; ADS_MODLIST mods; ADS_STATUS status; - char *upn, *new_dn, *name, *controlstr; + const char *upn, *new_dn, *name, *controlstr; + const char *objectClass[] = {"top", "person", "organizationalPerson", + "user", NULL}; if (fullname && *fullname) name = fullname; else name = user; @@ -63,14 +65,46 @@ ADS_STATUS ads_add_user_acct(ADS_STRUCT *ads, const char *user, if (!(mods = ads_init_mods(ctx))) goto done; - ads_mod_add(ctx, &mods, "cn", name); - ads_mod_add_var(ctx, &mods, LDAP_MOD_ADD, "objectClass", "top", - "person", "organizationalPerson", "user", NULL); - ads_mod_add(ctx, &mods, "userPrincipalName", upn); - ads_mod_add(ctx, &mods, "name", name); - ads_mod_add(ctx, &mods, "displayName", name); - ads_mod_add(ctx, &mods, "sAMAccountName", user); - ads_mod_add(ctx, &mods, "userAccountControl", controlstr); + ads_mod_str(ctx, &mods, "cn", name); + ads_mod_strlist(ctx, &mods, "objectClass", objectClass); + ads_mod_str(ctx, &mods, "userPrincipalName", upn); + ads_mod_str(ctx, &mods, "name", name); + ads_mod_str(ctx, &mods, "displayName", name); + ads_mod_str(ctx, &mods, "sAMAccountName", user); + ads_mod_str(ctx, &mods, "userAccountControl", controlstr); + status = ads_gen_add(ads, new_dn, mods); + + done: + talloc_destroy(ctx); + return status; +} + +ADS_STATUS ads_add_group_acct(ADS_STRUCT *ads, const char *group, + const char *comment) +{ + TALLOC_CTX *ctx; + ADS_MODLIST mods; + ADS_STATUS status; + char *new_dn; + const char *objectClass[] = {"top", "group", NULL}; + + if (!(ctx = talloc_init_named("ads_add_group_acct"))) + return ADS_ERROR(LDAP_NO_MEMORY); + + status = ADS_ERROR(LDAP_NO_MEMORY); + + if (!(new_dn = talloc_asprintf(ctx, "cn=%s,cn=Users,%s", group, + ads->bind_path))) + goto done; + if (!(mods = ads_init_mods(ctx))) + goto done; + + ads_mod_str(ctx, &mods, "cn", group); + ads_mod_strlist(ctx, &mods, "objectClass",objectClass); + ads_mod_str(ctx, &mods, "name", group); + if (comment) + ads_mod_str(ctx, &mods, "description", comment); + ads_mod_str(ctx, &mods, "sAMAccountName", group); status = ads_gen_add(ads, new_dn, mods); done: diff --git a/source3/libads/sasl.c b/source3/libads/sasl.c index eb29c71fce..1b55453cac 100644 --- a/source3/libads/sasl.c +++ b/source3/libads/sasl.c @@ -171,8 +171,7 @@ ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads) *p++ = max_msg_size>>16; *p++ = max_msg_size>>8; *p++ = max_msg_size; - snprintf(p, strlen(ads->bind_path)+1, "dn:%s", ads->bind_path); - p += strlen(ads->bind_path); + snprintf(p, strlen(ads->bind_path)+4, "dn:%s", ads->bind_path); output_token.length = strlen(ads->bind_path) + 8; |