summaryrefslogtreecommitdiff
path: root/source3/libads
diff options
context:
space:
mode:
Diffstat (limited to 'source3/libads')
-rw-r--r--source3/libads/ads_ldap.c16
-rw-r--r--source3/libads/ads_struct.c3
-rw-r--r--source3/libads/ads_utils.c46
-rw-r--r--source3/libads/kerberos_verify.c99
-rw-r--r--source3/libads/krb5_setpw.c37
-rw-r--r--source3/libads/ldap.c213
-rw-r--r--source3/libads/ldap_printer.c23
-rw-r--r--source3/libads/ldap_user.c8
-rw-r--r--source3/libads/sasl.c5
9 files changed, 211 insertions, 239 deletions
diff --git a/source3/libads/ads_ldap.c b/source3/libads/ads_ldap.c
index 97f12de0f7..dcceaaeb83 100644
--- a/source3/libads/ads_ldap.c
+++ b/source3/libads/ads_ldap.c
@@ -34,7 +34,7 @@ NTSTATUS ads_name_to_sid(ADS_STRUCT *ads,
int count;
ADS_STATUS rc;
void *res = NULL;
- char *exp;
+ char *ldap_exp;
uint32 t;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
char *escaped_name = escape_ldap_string_alloc(name);
@@ -45,15 +45,15 @@ NTSTATUS ads_name_to_sid(ADS_STRUCT *ads,
goto done;
}
- if (asprintf(&exp, "(|(sAMAccountName=%s)(userPrincipalName=%s@%s))",
+ if (asprintf(&ldap_exp, "(|(sAMAccountName=%s)(userPrincipalName=%s@%s))",
escaped_name, escaped_name, escaped_realm) == -1) {
DEBUG(1,("ads_name_to_sid: asprintf failed!\n"));
status = NT_STATUS_NO_MEMORY;
goto done;
}
- rc = ads_search_retry(ads, &res, exp, attrs);
- free(exp);
+ rc = ads_search_retry(ads, &res, ldap_exp, attrs);
+ free(ldap_exp);
if (!ADS_ERR_OK(rc)) {
DEBUG(1,("name_to_sid ads_search: %s\n", ads_errstr(rc)));
goto done;
@@ -102,7 +102,7 @@ NTSTATUS ads_sid_to_name(ADS_STRUCT *ads,
"sAMAccountType", NULL};
ADS_STATUS rc;
void *msg = NULL;
- char *exp = NULL;
+ char *ldap_exp = NULL;
char *sidstr = NULL;
uint32 atype;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
@@ -113,13 +113,13 @@ NTSTATUS ads_sid_to_name(ADS_STRUCT *ads,
goto done;
}
- if (asprintf(&exp, "(objectSid=%s)", sidstr) == -1) {
+ if (asprintf(&ldap_exp, "(objectSid=%s)", sidstr) == -1) {
DEBUG(1,("ads_sid_to_name: asprintf failed!\n"));
status = NT_STATUS_NO_MEMORY;
goto done;
}
- rc = ads_search_retry(ads, &msg, exp, attrs);
+ rc = ads_search_retry(ads, &msg, ldap_exp, attrs);
if (!ADS_ERR_OK(rc)) {
status = ads_ntstatus(rc);
DEBUG(1,("ads_sid_to_name ads_search: %s\n", ads_errstr(rc)));
@@ -146,7 +146,7 @@ NTSTATUS ads_sid_to_name(ADS_STRUCT *ads,
done:
if (msg) ads_msgfree(ads, msg);
- SAFE_FREE(exp);
+ SAFE_FREE(ldap_exp);
SAFE_FREE(sidstr);
return status;
diff --git a/source3/libads/ads_struct.c b/source3/libads/ads_struct.c
index 652bfe31be..dd31439d83 100644
--- a/source3/libads/ads_struct.c
+++ b/source3/libads/ads_struct.c
@@ -94,8 +94,7 @@ ADS_STRUCT *ads_init(const char *realm,
ads->server.workgroup = workgroup ? strdup(workgroup) : NULL;
ads->server.ldap_server = ldap_server? strdup(ldap_server) : NULL;
- /* we need to know if this is a foreign realm to know if we can
- use lp_ads_server() */
+ /* we need to know if this is a foreign realm */
if (realm && *realm && strcasecmp(lp_realm(), realm) != 0) {
ads->server.foreign = 1;
}
diff --git a/source3/libads/ads_utils.c b/source3/libads/ads_utils.c
index c56e7385a4..1aad0bed54 100644
--- a/source3/libads/ads_utils.c
+++ b/source3/libads/ads_utils.c
@@ -89,52 +89,6 @@ uint32 ads_uf2atype(uint32 uf)
}
/*
-translated the GROUP_CTRL Flags to GroupType (groupType)
-*/
-uint32 ads_gcb2gtype(uint16 gcb)
-{
- uint32 gtype = 0x00000000;
-
- if (gcb & GCB_ALIAS_GROUP) gtype |= GTYPE_SECURITY_BUILTIN_LOCAL_GROUP;
- else if(gcb & GCB_LOCAL_GROUP) gtype |= GTYPE_SECURITY_DOMAIN_LOCAL_GROUP;
- if (gcb & GCB_GLOBAL_GROUP) gtype |= GTYPE_SECURITY_GLOBAL_GROUP;
-
- return gtype;
-}
-
-/*
-translated the GroupType (groupType) to GROUP_CTRL Flags
-*/
-uint16 ads_gtype2gcb(uint32 gtype)
-{
- uint16 gcb = 0x0000;
-
- switch(gtype) {
- case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP:
- gcb = GCB_ALIAS_GROUP;
- break;
- case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP:
- gcb = GCB_LOCAL_GROUP;
- break;
- case GTYPE_SECURITY_GLOBAL_GROUP:
- gcb = GCB_GLOBAL_GROUP;
- break;
-
- case GTYPE_DISTRIBUTION_GLOBAL_GROUP:
- gcb = GCB_GLOBAL_GROUP;
- break;
- case GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP:
- gcb = GCB_LOCAL_GROUP;
- break;
- case GTYPE_DISTRIBUTION_UNIVERSAL_GROUP:
- gcb = GCB_GLOBAL_GROUP;
- break;
- }
-
- return gcb;
-}
-
-/*
get the accountType from the groupType
*/
uint32 ads_gtype2atype(uint32 gtype)
diff --git a/source3/libads/kerberos_verify.c b/source3/libads/kerberos_verify.c
index 35d429ca2a..25b7f9d948 100644
--- a/source3/libads/kerberos_verify.c
+++ b/source3/libads/kerberos_verify.c
@@ -33,21 +33,32 @@ NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket,
DATA_BLOB *ap_rep,
uint8 session_key[16])
{
- krb5_context context;
+ NTSTATUS sret = NT_STATUS_LOGON_FAILURE;
+ krb5_context context = NULL;
krb5_auth_context auth_context = NULL;
krb5_keytab keytab = NULL;
krb5_data packet;
krb5_ticket *tkt = NULL;
+ krb5_rcache rcache = NULL;
int ret, i;
- krb5_keyblock * key;
+ krb5_keyblock *key = NULL;
krb5_principal host_princ;
- char *host_princ_s;
+ char *host_princ_s = NULL;
fstring myname;
- char *password_s;
+ char *password_s = NULL;
krb5_data password;
krb5_enctype *enctypes = NULL;
+#if 0
+ krb5_address local_addr;
+ krb5_address remote_addr;
+#endif
BOOL auth_ok = False;
+ ZERO_STRUCT(packet);
+ ZERO_STRUCT(password);
+ ZERO_STRUCTP(auth_data);
+ ZERO_STRUCTP(ap_rep);
+
if (!secrets_init()) {
DEBUG(1,("secrets_init failed\n"));
return NT_STATUS_LOGON_FAILURE;
@@ -71,35 +82,63 @@ NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket,
ret = krb5_set_default_realm(context, ads->auth.realm);
if (ret) {
DEBUG(1,("krb5_set_default_realm failed (%s)\n", error_message(ret)));
- return NT_STATUS_LOGON_FAILURE;
+ sret = NT_STATUS_LOGON_FAILURE;
+ goto out;
}
- /* this whole process is far more complex than I would
+ /* 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;
+ sret = NT_STATUS_LOGON_FAILURE;
+ goto out;
}
fstrcpy(myname, global_myname());
- strlower(myname);
+ strlower_m(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;
+ sret = NT_STATUS_LOGON_FAILURE;
+ goto out;
}
+ /*
+ * JRA. We must set the rcache and the allowed addresses in the auth_context
+ * here. This will prevent replay attacks and ensure the client has got a key from
+ * the correct IP address.
+ */
+
+ ret = krb5_get_server_rcache(context, krb5_princ_component(context, host_princ, 0), &rcache);
+ if (ret) {
+ DEBUG(1,("krb5_get_server_rcache failed (%s)\n", error_message(ret)));
+ sret = NT_STATUS_LOGON_FAILURE;
+ goto out;
+ }
+
+ ret = krb5_auth_con_setrcache(context, auth_context, rcache);
+ if (ret) {
+ DEBUG(1,("krb5_auth_con_setrcache failed (%s)\n", error_message(ret)));
+ sret = NT_STATUS_LOGON_FAILURE;
+ goto out;
+ }
+
+ /* Now we need to add the addresses.... JRA. */
+
if (!(key = (krb5_keyblock *)malloc(sizeof(*key)))) {
- return NT_STATUS_NO_MEMORY;
+ sret = NT_STATUS_NO_MEMORY;
+ goto out;
}
if ((ret = get_kerberos_allowed_etypes(context, &enctypes))) {
DEBUG(1,("krb5_get_permitted_enctypes failed (%s)\n",
error_message(ret)));
- return NT_STATUS_LOGON_FAILURE;
+ sret = NT_STATUS_LOGON_FAILURE;
+ goto out;
}
/* we need to setup a auth context with each possible encoding type in turn */
@@ -124,23 +163,26 @@ NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket,
if (!auth_ok) {
DEBUG(3,("krb5_rd_req with auth failed (%s)\n",
error_message(ret)));
- return NT_STATUS_LOGON_FAILURE;
+ sret = NT_STATUS_LOGON_FAILURE;
+ goto out;
}
ret = krb5_mk_rep(context, auth_context, &packet);
if (ret) {
DEBUG(3,("Failed to generate mutual authentication reply (%s)\n",
error_message(ret)));
- krb5_auth_con_free(context, auth_context);
- return NT_STATUS_LOGON_FAILURE;
+ sret = NT_STATUS_LOGON_FAILURE;
+ goto out;
}
*ap_rep = data_blob(packet.data, packet.length);
free(packet.data);
- krb5_get_smb_session_key(context, auth_context, session_key);
- DEBUG(0,("SMB session key (from ticket) follows:\n"));
- dump_data(0, session_key, 16);
+ get_krb5_smb_session_key(context, auth_context, session_key);
+#ifdef DEBUG_PASSWORD
+ DEBUG(10,("SMB session key (from ticket) follows:\n"));
+ dump_data(10, session_key, 16);
+#endif
#if 0
file_save("/tmp/ticket.dat", ticket->data, ticket->length);
@@ -165,15 +207,30 @@ NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket,
principal))) {
DEBUG(3,("krb5_unparse_name failed (%s)\n",
error_message(ret)));
+ sret = NT_STATUS_LOGON_FAILURE;
+ goto out;
+ }
+
+ sret = NT_STATUS_OK;
+
+ out:
+
+ if (!NT_STATUS_IS_OK(sret))
data_blob_free(auth_data);
+
+ if (!NT_STATUS_IS_OK(sret))
data_blob_free(ap_rep);
+
+ SAFE_FREE(host_princ_s);
+ SAFE_FREE(password_s);
+
+ if (auth_context)
krb5_auth_con_free(context, auth_context);
- return NT_STATUS_LOGON_FAILURE;
- }
- krb5_auth_con_free(context, auth_context);
+ if (context)
+ krb5_free_context(context);
- return NT_STATUS_OK;
+ return sret;
}
#endif /* HAVE_KRB5 */
diff --git a/source3/libads/krb5_setpw.c b/source3/libads/krb5_setpw.c
index 214871b3fb..80ef6cdf01 100644
--- a/source3/libads/krb5_setpw.c
+++ b/source3/libads/krb5_setpw.c
@@ -195,9 +195,9 @@ static const struct kpasswd_errors {
{0, NULL}
};
-static krb5_error_code krb5_setpw_result_code_string(krb5_context context,
- int result_code,
- const char **code_string)
+static krb5_error_code setpw_result_code_string(krb5_context context,
+ int result_code,
+ const char **code_string)
{
unsigned int idx = 0;
@@ -311,7 +311,7 @@ static krb5_error_code parse_setpw_reply(krb5_context context,
return 0;
else {
const char *errstr;
- krb5_setpw_result_code_string(context, res_code, &errstr);
+ setpw_result_code_string(context, res_code, &errstr);
DEBUG(1, ("Error changing password: %s\n", errstr));
switch(res_code) {
@@ -457,8 +457,8 @@ static ADS_STATUS do_krb5_kpasswd_request(krb5_context context,
return ADS_SUCCESS;
}
-ADS_STATUS krb5_set_password(const char *kdc_host, const char *princ, const char *newpw,
- int time_offset)
+ADS_STATUS ads_krb5_set_password(const char *kdc_host, const char *princ,
+ const char *newpw, int time_offset)
{
ADS_STATUS aret;
@@ -570,11 +570,11 @@ kerb_prompter(krb5_context ctx, void *data,
return 0;
}
-static ADS_STATUS krb5_chg_password(const char *kdc_host,
- const char *principal,
- const char *oldpw,
- const char *newpw,
- int time_offset)
+static ADS_STATUS ads_krb5_chg_password(const char *kdc_host,
+ const char *principal,
+ const char *oldpw,
+ const char *newpw,
+ int time_offset)
{
ADS_STATUS aret;
krb5_error_code ret;
@@ -648,11 +648,11 @@ ADS_STATUS kerberos_set_password(const char *kpasswd_server,
}
if (!strcmp(auth_principal, target_principal))
- return krb5_chg_password(kpasswd_server, target_principal,
- auth_password, new_password, time_offset);
+ return ads_krb5_chg_password(kpasswd_server, target_principal,
+ auth_password, new_password, time_offset);
else
- return krb5_set_password(kpasswd_server, target_principal,
- new_password, time_offset);
+ return ads_krb5_set_password(kpasswd_server, target_principal,
+ new_password, time_offset);
}
@@ -671,15 +671,16 @@ ADS_STATUS ads_set_machine_password(ADS_STRUCT *ads,
char *host = strdup(hostname);
char *principal;
- strlower(host);
+ strlower_m(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->auth.realm);
+ asprintf(&principal, "%s$@%s", host, ads->config.realm);
- status = krb5_set_password(ads->auth.kdc_server, principal, password, ads->auth.time_offset);
+ status = ads_krb5_set_password(ads->auth.kdc_server, principal,
+ password, ads->auth.time_offset);
free(host);
free(principal);
diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c
index 3ce80975da..92f7f7645a 100644
--- a/source3/libads/ldap.c
+++ b/source3/libads/ldap.c
@@ -41,6 +41,9 @@
/*
try a connection to a given ldap server, returning True and setting the servers IP
in the ads struct if successful
+
+ TODO : add a negative connection cache in here leveraged off of the one
+ found in the rpc code. --jerry
*/
static BOOL ads_try_connect(ADS_STRUCT *ads, const char *server, unsigned port)
{
@@ -90,133 +93,81 @@ static BOOL ads_try_connect_uri(ADS_STRUCT *ads)
return False;
}
-/* used by the IP comparison function */
-struct ldap_ip {
- struct in_addr ip;
- unsigned port;
-};
-
-/* compare 2 ldap IPs by nearness to our interfaces - used in qsort */
-static int ldap_ip_compare(struct ldap_ip *ip1, struct ldap_ip *ip2)
-{
- return ip_compare(&ip1->ip, &ip2->ip);
-}
+/**********************************************************************
+ Try to find an AD dc using our internal name resolution routines
+ Try the realm first and then then workgroup name if netbios is not
+ disabled
+**********************************************************************/
-/* try connecting to a ldap server via DNS */
-static BOOL ads_try_dns(ADS_STRUCT *ads)
+static BOOL ads_find_dc(ADS_STRUCT *ads)
{
const char *c_realm;
- const char *ptr;
- char *realm;
- char *list = NULL;
- pstring tok;
- struct ldap_ip *ip_list;
int count, i=0;
+ struct ip_service *ip_list;
+ pstring realm;
+ BOOL got_realm = False;
+ /* realm */
c_realm = ads->server.realm;
if (!c_realm || !*c_realm) {
c_realm = lp_realm();
}
- if (!c_realm || !*c_realm) {
- c_realm = ads->server.workgroup;
- }
- if (!c_realm || !*c_realm) {
- c_realm = lp_workgroup();
- }
- if (!c_realm) {
- return False;
- }
- realm = smb_xstrdup(c_realm);
+ if ( c_realm )
+ got_realm = True;
- DEBUG(6,("ads_try_dns: looking for realm '%s'\n", realm));
- if (ldap_domain2hostlist(realm, &list) != LDAP_SUCCESS) {
- SAFE_FREE(realm);
- return False;
+
+again:
+ /* we need to try once with the realm name and fallback to the
+ netbios domain name if we fail (if netbios has not been disabled */
+
+ if ( !got_realm && !lp_disable_netbios() ) {
+ c_realm = ads->server.workgroup;
+ if (!c_realm || !*c_realm)
+ c_realm = lp_workgroup();
+ if (!c_realm)
+ return False;
}
+
+ pstrcpy( realm, c_realm );
- DEBUG(6,("ads_try_dns: ldap realm '%s' host list '%s'\n", realm, list));
- SAFE_FREE(realm);
+ DEBUG(6,("ads_find_dc: looking for %s '%s'\n",
+ (got_realm ? "realm" : "domain"), realm));
- count = count_chars(list, ' ') + 1;
- ip_list = malloc(count * sizeof(struct ldap_ip));
- if (!ip_list) {
- return False;
- }
-
- ptr = list;
- while (next_token(&ptr, tok, " ", sizeof(tok))) {
- unsigned port = LDAP_PORT;
- char *p = strchr(tok, ':');
- if (p) {
- *p = 0;
- port = atoi(p+1);
- }
- ip_list[i].ip = *interpret_addr2(tok);
- ip_list[i].port = port;
- if (!is_zero_ip(ip_list[i].ip)) {
- i++;
+ if ( !get_sorted_dc_list(realm, &ip_list, &count, got_realm) ) {
+ /* fall back to netbios if we can */
+ if ( got_realm && !lp_disable_netbios() ) {
+ got_realm = False;
+ goto again;
}
+
+ return False;
}
- free(list);
-
- count = i;
-
- /* we sort the list of addresses by closeness to our interfaces. This
- tries to prevent us using a DC on the other side of the country */
- if (count > 1) {
- qsort(ip_list, count, sizeof(struct ldap_ip),
- QSORT_CAST ldap_ip_compare);
- }
-
- for (i=0;i<count;i++) {
- if (ads_try_connect(ads, inet_ntoa(ip_list[i].ip), ip_list[i].port)) {
- free(ip_list);
+
+ /* if we fail this loop, then giveup since all the IP addresses returned were dead */
+ for ( i=0; i<count; i++ ) {
+ /* since this is an ads conection request, default to LDAP_PORT is not set */
+ int port = (ip_list[i].port!=PORT_NONE) ? ip_list[i].port : LDAP_PORT;
+ fstring server;
+
+ fstrcpy( server, inet_ntoa(ip_list[i].ip) );
+
+ if ( !NT_STATUS_IS_OK(check_negative_conn_cache(realm, server)) )
+ continue;
+
+ if ( ads_try_connect(ads, server, port) ) {
+ SAFE_FREE(ip_list);
return True;
}
+
+ /* keep track of failures */
+ add_failed_connection_entry( realm, server, NT_STATUS_UNSUCCESSFUL );
}
SAFE_FREE(ip_list);
+
return False;
}
-/* try connecting to a ldap server via netbios */
-static BOOL ads_try_netbios(ADS_STRUCT *ads)
-{
- struct in_addr *ip_list, pdc_ip;
- int count;
- int i;
- const char *workgroup = ads->server.workgroup;
- BOOL list_ordered;
-
- if (!workgroup) {
- workgroup = lp_workgroup();
- }
-
- DEBUG(6,("ads_try_netbios: looking for workgroup '%s'\n", workgroup));
-
- /* try the PDC first */
- if (get_pdc_ip(workgroup, &pdc_ip)) {
- DEBUG(6,("ads_try_netbios: trying server '%s'\n",
- inet_ntoa(pdc_ip)));
- if (ads_try_connect(ads, inet_ntoa(pdc_ip), LDAP_PORT))
- return True;
- }
-
- /* now any DC, including backups */
- if (get_dc_list(workgroup, &ip_list, &count, &list_ordered)) {
- for (i=0;i<count;i++) {
- DEBUG(6,("ads_try_netbios: trying server '%s'\n",
- inet_ntoa(ip_list[i])));
- if (ads_try_connect(ads, inet_ntoa(ip_list[i]), LDAP_PORT)) {
- free(ip_list);
- return True;
- }
- }
- free(ip_list);
- }
-
- return False;
-}
/**
* Connect to the LDAP server
@@ -244,20 +195,7 @@ ADS_STATUS ads_connect(ADS_STRUCT *ads)
goto got_connection;
}
- /* try with a smb.conf ads server setting if we are connecting
- to the primary workgroup or realm */
- if (!ads->server.foreign &&
- ads_try_connect(ads, lp_ads_server(), LDAP_PORT)) {
- goto got_connection;
- }
-
- /* try via DNS */
- if (ads_try_dns(ads)) {
- goto got_connection;
- }
-
- /* try via netbios lookups */
- if (!lp_disable_netbios() && ads_try_netbios(ads)) {
+ if (ads_find_dc(ads)) {
goto got_connection;
}
@@ -278,7 +216,7 @@ got_connection:
/* by default use the machine account */
fstring myname;
fstrcpy(myname, global_myname());
- strlower(myname);
+ strlower_m(myname);
asprintf(&ads->auth.user_name, "HOST/%s", myname);
}
@@ -400,7 +338,7 @@ static char **ads_pull_strvals(TALLOC_CTX *ctx, const char **in_vals)
* again when the entire search is complete
* @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 scope Scope of search (LDAP_SCOPE_BASE | LDAP_SCOPE_ONE | LDAP_SCOPE_SUBTREE)
* @param expr 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()
@@ -540,7 +478,7 @@ done:
* all entries in a large search.
* @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 scope Scope of search (LDAP_SCOPE_BASE | LDAP_SCOPE_ONE | LDAP_SCOPE_SUBTREE)
* @param expr Search expression
* @param attrs Attributes to retrieve
* @param res ** which will contain results - free res* with ads_msgfree()
@@ -587,7 +525,7 @@ ADS_STATUS ads_do_search_all(ADS_STRUCT *ads, const char *bind_path,
* runs the function as each page is returned, using ads_process_results()
* @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 scope Scope of search (LDAP_SCOPE_BASE | LDAP_SCOPE_ONE | LDAP_SCOPE_SUBTREE)
* @param expr 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
@@ -629,7 +567,7 @@ ADS_STATUS ads_do_search_all_fn(ADS_STRUCT *ads, const char *bind_path,
* Do a search with a timeout.
* @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 scope Scope of search (LDAP_SCOPE_BASE | LDAP_SCOPE_ONE | LDAP_SCOPE_SUBTREE)
* @param expr Search expression
* @param attrs Attributes to retrieve
* @param res ** which will contain results - free res* with ads_msgfree()
@@ -749,14 +687,15 @@ void ads_memfree(ADS_STRUCT *ads, void *mem)
/**
* Get a dn from search results
* @param ads connection to ads server
- * @param res Search results
+ * @param msg Search result
* @return dn string
**/
-char *ads_get_dn(ADS_STRUCT *ads, void *res)
+char *ads_get_dn(ADS_STRUCT *ads, void *msg)
{
char *utf8_dn, *unix_dn;
- utf8_dn = ldap_get_dn(ads->ld, res);
+ utf8_dn = ldap_get_dn(ads->ld, msg);
+
pull_utf8_allocate((void **) &unix_dn, utf8_dn);
ldap_memfree(utf8_dn);
return unix_dn;
@@ -998,7 +937,7 @@ ADS_STATUS ads_del_dn(ADS_STRUCT *ads, char *del_dn)
return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
}
- ret = ldap_delete(ads->ld, utf8_dn);
+ ret = ldap_delete_s(ads->ld, utf8_dn);
return ADS_ERROR(ret);
}
@@ -1058,13 +997,13 @@ static ADS_STATUS ads_add_machine_acct(ADS_STRUCT *ads, const char *hostname,
psp = talloc_asprintf(ctx, "HOST/%s.%s",
hostname,
ads->config.realm);
- strlower(&psp[5]);
+ strlower_m(&psp[5]);
servicePrincipalName[1] = psp;
servicePrincipalName[2] = talloc_asprintf(ctx, "CIFS/%s", hostname);
psp2 = talloc_asprintf(ctx, "CIFS/%s.%s",
hostname,
ads->config.realm);
- strlower(&psp2[5]);
+ strlower_m(&psp2[5]);
servicePrincipalName[3] = psp2;
free(ou_str);
@@ -1078,6 +1017,7 @@ static ADS_STATUS ads_add_machine_acct(ADS_STRUCT *ads, const char *hostname,
#ifndef ENCTYPE_ARCFOUR_HMAC
acct_control |= UF_USE_DES_KEY_ONLY;
#endif
+
if (!(controlstr = talloc_asprintf(ctx, "%u", acct_control)))
goto done;
@@ -1142,7 +1082,7 @@ static void dump_guid(const char *field, struct berval **values)
GUID guid;
for (i=0; values[i]; i++) {
memcpy(guid.info, values[i]->bv_val, sizeof(guid.info));
- printf("%s: %s\n", field, uuid_string_static(guid));
+ printf("%s: %s\n", field, smb_uuid_string_static(guid));
}
}
@@ -1345,7 +1285,7 @@ ADS_STATUS ads_join_realm(ADS_STRUCT *ads, const char *hostname,
/* hostname must be lowercase */
host = strdup(hostname);
- strlower(host);
+ strlower_m(host);
status = ads_find_machine_acct(ads, (void **)&res, host);
if (ADS_ERR_OK(status) && ads_count_replies(ads, res) == 1) {
@@ -1384,13 +1324,13 @@ ADS_STATUS ads_join_realm(ADS_STRUCT *ads, const char *hostname,
ADS_STATUS ads_leave_realm(ADS_STRUCT *ads, const char *hostname)
{
ADS_STATUS status;
- void *res;
+ void *res, *msg;
char *hostnameDN, *host;
int rc;
/* hostname must be lowercase */
host = strdup(hostname);
- strlower(host);
+ strlower_m(host);
status = ads_find_machine_acct(ads, &res, host);
if (!ADS_ERR_OK(status)) {
@@ -1398,7 +1338,12 @@ ADS_STATUS ads_leave_realm(ADS_STRUCT *ads, const char *hostname)
return status;
}
- hostnameDN = ads_get_dn(ads, (LDAPMessage *)res);
+ msg = ads_first_entry(ads, res);
+ if (!msg) {
+ return ADS_ERROR_SYSTEM(ENOENT);
+ }
+
+ hostnameDN = ads_get_dn(ads, (LDAPMessage *)msg);
rc = ldap_delete_s(ads->ld, hostnameDN);
ads_memfree(ads, hostnameDN);
if (rc != LDAP_SUCCESS) {
diff --git a/source3/libads/ldap_printer.c b/source3/libads/ldap_printer.c
index f5cd4f2885..b650a5eb38 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,
const char *printer, const char *servername)
{
ADS_STATUS status;
- char *srv_dn, **srv_cn, *exp;
+ char *srv_dn, **srv_cn, *s;
const char *attrs[] = {"*", "nTSecurityDescriptor", NULL};
status = ads_find_machine_acct(ads, res, servername);
@@ -44,15 +44,29 @@ ADS_STATUS ads_find_printer_on_server(ADS_STRUCT *ads, void **res,
srv_cn = ldap_explode_dn(srv_dn, 1);
ads_msgfree(ads, *res);
- asprintf(&exp, "(cn=%s-%s)", srv_cn[0], printer);
- status = ads_search(ads, res, exp, attrs);
+ asprintf(&s, "(cn=%s-%s)", srv_cn[0], printer);
+ status = ads_search(ads, res, s, attrs);
ldap_memfree(srv_dn);
ldap_value_free(srv_cn);
- free(exp);
+ free(s);
return status;
}
+ADS_STATUS ads_find_printers(ADS_STRUCT *ads, void **res)
+{
+ char *ldap_expr;
+ const char *attrs[] = { "objectClass", "printerName", "location", "driverName",
+ "serverName", "description", NULL };
+
+ /* For the moment only display all printers */
+
+ ldap_expr = "(&(!(showInAdvancedViewOnly=TRUE))(uncName=*)"
+ "(objectCategory=printQueue))";
+
+ return ads_search(ads, res, ldap_expr, attrs);
+}
+
/*
modify a printer entry in the directory
*/
@@ -338,4 +352,3 @@ BOOL get_local_printer_publishing_data(TALLOC_CTX *mem_ctx,
}
#endif
-
diff --git a/source3/libads/ldap_user.c b/source3/libads/ldap_user.c
index 7efe5338f3..e70249dd78 100644
--- a/source3/libads/ldap_user.c
+++ b/source3/libads/ldap_user.c
@@ -28,16 +28,16 @@
ADS_STATUS ads_find_user_acct(ADS_STRUCT *ads, void **res, const char *user)
{
ADS_STATUS status;
- char *exp;
+ char *ldap_exp;
const char *attrs[] = {"*", NULL};
char *escaped_user = escape_ldap_string_alloc(user);
if (!escaped_user) {
return ADS_ERROR(LDAP_NO_MEMORY);
}
- asprintf(&exp, "(samAccountName=%s)", escaped_user);
- status = ads_search(ads, res, exp, attrs);
- SAFE_FREE(exp);
+ asprintf(&ldap_exp, "(samAccountName=%s)", escaped_user);
+ status = ads_search(ads, res, ldap_exp, attrs);
+ SAFE_FREE(ldap_exp);
SAFE_FREE(escaped_user);
return status;
}
diff --git a/source3/libads/sasl.c b/source3/libads/sasl.c
index 29d4533a54..598208b17f 100644
--- a/source3/libads/sasl.c
+++ b/source3/libads/sasl.c
@@ -198,8 +198,11 @@ static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads)
if (ads_kinit_password(ads) == 0) {
status = ads_sasl_spnego_krb5_bind(ads, principal);
}
- if (ADS_ERR_OK(status))
+ /* only fallback to NTLMSSP if allowed */
+ if (ADS_ERR_OK(status) ||
+ !(ads->auth.flags & ADS_AUTH_ALLOW_NTLMSSP)) {
return status;
+ }
}
#endif