From 1f31ace6cb771d7bf0b64091fba1d24c466ad4e5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 19 Dec 2001 12:21:12 +0000 Subject: much better ADS error handling system (This used to be commit 05a90a28843e0d69183a49a76617c5f32817df16) --- source3/include/ads.h | 22 +++- source3/libads/ads_struct.c | 34 +----- source3/libads/krb5_setpw.c | 36 +++--- source3/libads/ldap.c | 234 +++++++++++++++++++++++--------------- source3/libads/sasl.c | 54 +++++---- source3/nsswitch/winbindd_ads.c | 122 ++++++++++---------- source3/nsswitch/winbindd_proto.h | 18 +-- source3/script/mkproto.awk | 2 +- source3/utils/net_ads.c | 44 ++++--- 9 files changed, 301 insertions(+), 265 deletions(-) diff --git a/source3/include/ads.h b/source3/include/ads.h index 4a20d0e79f..884f2aa6ef 100644 --- a/source3/include/ads.h +++ b/source3/include/ads.h @@ -18,16 +18,26 @@ typedef struct { char *server_realm; } ADS_STRUCT; +/* there are 4 possible types of errors the ads subsystem can produce */ +enum ads_error_type {ADS_ERROR_KRB5, ADS_ERROR_GSS, + ADS_ERROR_LDAP, ADS_ERROR_SYSTEM}; + typedef struct { - /* Type of error returned by ads_connect: */ - /* True corresponds GSS API, False - LDAP */ - int error_type; - /* For error_type = False rc describes LDAP error */ + enum ads_error_type error_type; int rc; - /* For error_type = True rc and minor_status describe GSS API error */ + /* For error_type = ADS_ERROR_GSS minor_status describe GSS API error */ /* Where rc represents major_status of GSS API error */ int minor_status; -} ADS_RETURN_CODE; +} ADS_STATUS; + +/* macros to simplify error returning */ +#define ADS_ERROR(rc) ads_build_error(ADS_ERROR_LDAP, rc, 0); +#define ADS_ERROR_SYSTEM(rc) ads_build_error(ADS_ERROR_SYSTEM, rc, 0); +#define ADS_ERROR_KRB5(rc) ads_build_error(ADS_ERROR_KRB5, rc, 0); +#define ADS_ERROR_GSS(rc, minor) ads_build_error(ADS_ERROR_GSS, rc, minor); + +#define ADS_ERR_OK(status) ((status).rc == 0) +#define ADS_SUCCESS ADS_ERROR(0) /* time between reconnect attempts */ #define ADS_RECONNECT_TIME 5 diff --git a/source3/libads/ads_struct.c b/source3/libads/ads_struct.c index 83d423104e..013491eaed 100644 --- a/source3/libads/ads_struct.c +++ b/source3/libads/ads_struct.c @@ -22,6 +22,10 @@ #include "includes.h" +/* return a dn of the form "dc=AA,dc=BB,dc=CC" from a + realm of the form AA.BB.CC + caller must free +*/ char *ads_build_dn(const char *realm) { char *p, *r; @@ -156,33 +160,3 @@ void ads_destroy(ADS_STRUCT **ads) SAFE_FREE(*ads); } } - -#if HAVE_KRB5 -static void ads_display_status_helper(const char *m, uint32 code, int type) -{ - int maj_stat, min_stat; - gss_buffer_desc msg; - int msg_ctx; - - msg_ctx = 0; - while (1) { - maj_stat = gss_display_status(&min_stat, code, - type, GSS_C_NULL_OID, - &msg_ctx, &msg); - DEBUG(1, ("GSS-API error %s: %s\n", m, - (char *)msg.value)); - (void) gss_release_buffer(&min_stat, &msg); - - if (!msg_ctx) - break; - } -} -#endif - -void ads_display_status(const char *msg, int maj_stat,int min_stat) -{ -#if HAVE_KRB5 - ads_display_status_helper(msg, maj_stat, GSS_C_GSS_CODE); - ads_display_status_helper(msg, min_stat, GSS_C_MECH_CODE); -#endif -} diff --git a/source3/libads/krb5_setpw.c b/source3/libads/krb5_setpw.c index 1c3b15d2a5..b46a579263 100644 --- a/source3/libads/krb5_setpw.c +++ b/source3/libads/krb5_setpw.c @@ -212,8 +212,8 @@ static krb5_error_code parse_setpw_reply(krb5_context context, return 0; } -NTSTATUS krb5_set_password(const char *kdc_host, const char *hostname, - const char *realm, const char *newpw) +ADS_STATUS krb5_set_password(const char *kdc_host, const char *hostname, + const char *realm, const char *newpw) { krb5_context context; krb5_auth_context auth_context = NULL; @@ -229,13 +229,13 @@ NTSTATUS krb5_set_password(const char *kdc_host, const char *hostname, ret = krb5_init_context(&context); if (ret) { DEBUG(1,("Failed to init krb5 context (%s)\n", error_message(ret))); - return NT_STATUS_UNSUCCESSFUL; + return ADS_ERROR_KRB5(ret); } ret = krb5_cc_default(context, &ccache); if (ret) { DEBUG(1,("Failed to get default creds (%s)\n", error_message(ret))); - return NT_STATUS_UNSUCCESSFUL; + return ADS_ERROR_KRB5(ret); } ZERO_STRUCT(creds); @@ -244,7 +244,7 @@ NTSTATUS krb5_set_password(const char *kdc_host, const char *hostname, ret = krb5_parse_name(context, princ_name, &creds.server); if (ret) { DEBUG(1,("Failed to parse kadmin/changepw (%s)\n", error_message(ret))); - return NT_STATUS_UNSUCCESSFUL; + return ADS_ERROR_KRB5(ret); } free(princ_name); @@ -252,7 +252,7 @@ NTSTATUS krb5_set_password(const char *kdc_host, const char *hostname, ret = krb5_parse_name(context, princ_name, &principal); if (ret) { DEBUG(1,("Failed to parse %s (%s)\n", princ_name, error_message(ret))); - return NT_STATUS_UNSUCCESSFUL; + return ADS_ERROR_KRB5(ret); } free(princ_name); @@ -263,27 +263,28 @@ NTSTATUS krb5_set_password(const char *kdc_host, const char *hostname, if (ret) { DEBUG(1,("Failed to get principal from ccache (%s)\n", error_message(ret))); - return NT_STATUS_UNSUCCESSFUL; + return ADS_ERROR_KRB5(ret); } ret = krb5_get_credentials(context, 0, ccache, &creds, &credsp); if (ret) { DEBUG(1,("krb5_get_credentials failed (%s)\n", error_message(ret))); - return NT_STATUS_UNSUCCESSFUL; + return ADS_ERROR_KRB5(ret); } ret = krb5_mk_req_extended(context, &auth_context, AP_OPTS_USE_SUBKEY, NULL, credsp, &ap_req); if (ret) { DEBUG(1,("krb5_mk_req_extended failed (%s)\n", error_message(ret))); - return NT_STATUS_UNSUCCESSFUL; + return ADS_ERROR_KRB5(ret); } sock = open_udp_socket(kdc_host, DEFAULT_KPASSWD_PORT); if (sock == -1) { + int rc = errno; DEBUG(1,("failed to open kpasswd socket to %s (%s)\n", kdc_host, strerror(errno))); - return NT_STATUS_UNSUCCESSFUL; + return ADS_ERROR_SYSTEM(rc); } addr_len = sizeof(remote_addr); @@ -301,19 +302,19 @@ NTSTATUS krb5_set_password(const char *kdc_host, const char *hostname, ret = krb5_auth_con_setaddrs(context, auth_context, &local_kaddr, NULL); if (ret) { DEBUG(1,("krb5_auth_con_setaddrs failed (%s)\n", error_message(ret))); - return NT_STATUS_UNSUCCESSFUL; + return ADS_ERROR_KRB5(ret); } ret = build_setpw_request(context, auth_context, &ap_req, hostname, realm, newpw, &chpw_req); if (ret) { DEBUG(1,("build_setpw_request failed (%s)\n", error_message(ret))); - return NT_STATUS_UNSUCCESSFUL; + return ADS_ERROR_KRB5(ret); } if (write(sock, chpw_req.data, chpw_req.length) != chpw_req.length) { DEBUG(1,("send of chpw failed (%s)\n", strerror(errno))); - return NT_STATUS_UNSUCCESSFUL; + return ADS_ERROR(LDAP_ENCODING_ERROR); } free(chpw_req.data); @@ -323,8 +324,7 @@ NTSTATUS krb5_set_password(const char *kdc_host, const char *hostname, ret = read(sock, chpw_rep.data, chpw_rep.length); if (ret < 0) { - DEBUG(1,("recv of chpw reply failed (%s)\n", strerror(errno))); - return NT_STATUS_UNSUCCESSFUL; + return ADS_ERROR_SYSTEM(errno); } close(sock); @@ -334,7 +334,7 @@ NTSTATUS krb5_set_password(const char *kdc_host, const char *hostname, if (ret) { DEBUG(1,("krb5_auth_con_setaddrs on reply failed (%s)\n", error_message(ret))); - return NT_STATUS_UNSUCCESSFUL; + return ADS_ERROR_KRB5(ret); } ret = parse_setpw_reply(context, auth_context, &chpw_rep); @@ -343,10 +343,10 @@ NTSTATUS krb5_set_password(const char *kdc_host, const char *hostname, if (ret) { DEBUG(1,("parse_setpw_reply failed (%s)\n", error_message(ret))); - return NT_STATUS_UNSUCCESSFUL; + return ADS_ERROR_KRB5(ret); } - return NT_STATUS_OK; + return ADS_SUCCESS; } #endif diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c index b41a864ae2..3452614315 100644 --- a/source3/libads/ldap.c +++ b/source3/libads/ldap.c @@ -23,39 +23,83 @@ #ifdef HAVE_ADS -/* return a dn of the form "dc=AA,dc=BB,dc=CC" from a - realm of the form AA.BB.CC - caller must free +/* + build a ADS_STATUS structure +*/ +ADS_STATUS ads_build_error(enum ads_error_type etype, + int rc, int minor_status) +{ + ADS_STATUS ret; + ret.error_type = etype; + ret.rc = rc; + ret.minor_status = minor_status; + return ret; +} + +/* + do a rough conversion between ads error codes and NT status codes + we'll need to fill this in more */ +NTSTATUS ads_ntstatus(ADS_STATUS rc) +{ + if (ADS_ERR_OK(rc)) return NT_STATUS_OK; + return NT_STATUS_UNSUCCESSFUL; +} + /* return a string for an error from a ads routine */ -char *ads_errstr(int rc) +const char *ads_errstr(ADS_STATUS status) { - return ldap_err2string(rc); + gss_buffer_desc msg1, msg2; + uint32 minor; + int msg_ctx; + static char *ret; + + SAFE_FREE(ret); + msg_ctx = 0; + + switch (status.error_type) { + case ADS_ERROR_KRB5: + return error_message(status.rc); + case ADS_ERROR_LDAP: + return ldap_err2string(status.rc); + case ADS_ERROR_SYSTEM: + return strerror(status.rc); + case ADS_ERROR_GSS: + msg1.value = NULL; + msg2.value = NULL; + gss_display_status(&minor, status.rc, GSS_C_GSS_CODE, + GSS_C_NULL_OID, &msg_ctx, &msg1); + gss_display_status(&minor, status.minor_status, GSS_C_MECH_CODE, + GSS_C_NULL_OID, &msg_ctx, &msg2); + asprintf(&ret, "%s : %s", (char *)msg1.value, (char *)msg2.value); + gss_release_buffer(&minor, &msg1); + gss_release_buffer(&minor, &msg2); + return ret; + } + + return "Unknown ADS error type!?"; } /* connect to the LDAP server */ -ADS_RETURN_CODE ads_connect(ADS_STRUCT *ads) +ADS_STATUS ads_connect(ADS_STRUCT *ads) { int version = LDAP_VERSION3; - ADS_RETURN_CODE rc; - - rc.error_type = False; + ADS_STATUS status; ads->last_attempt = time(NULL); ads->ld = ldap_open(ads->ldap_server, ads->ldap_port); if (!ads->ld) { - rc.rc = LDAP_SERVER_DOWN; - return rc; + return ADS_ERROR_SYSTEM(errno) } - if (!ads_server_info(ads)) { + status = ads_server_info(ads); + if (!ADS_ERR_OK(status)) { DEBUG(1,("Failed to get ldap server info\n")); - rc.rc = LDAP_SERVER_DOWN; - return rc; + return status; } ldap_set_option(ads->ld, LDAP_OPT_PROTOCOL_VERSION, &version); @@ -64,33 +108,35 @@ ADS_RETURN_CODE ads_connect(ADS_STRUCT *ads) ads_kinit_password(ads); } - rc = ads_sasl_bind(ads); - return rc; + return ads_sasl_bind(ads); } /* do a search with a timeout */ -int ads_do_search(ADS_STRUCT *ads, const char *bind_path, int scope, const char *exp, - const char **attrs, void **res) +ADS_STATUS ads_do_search(ADS_STRUCT *ads, const char *bind_path, int scope, + const char *exp, + const char **attrs, void **res) { struct timeval timeout; + int rc; timeout.tv_sec = ADS_SEARCH_TIMEOUT; timeout.tv_usec = 0; *res = NULL; - return ldap_search_ext_s(ads->ld, - bind_path, scope, - exp, attrs, 0, NULL, NULL, - &timeout, LDAP_NO_LIMIT, (LDAPMessage **)res); + rc = ldap_search_ext_s(ads->ld, + bind_path, scope, + exp, attrs, 0, NULL, NULL, + &timeout, LDAP_NO_LIMIT, (LDAPMessage **)res); + return ADS_ERROR(rc); } /* do a general ADS search */ -int ads_search(ADS_STRUCT *ads, void **res, - const char *exp, - const char **attrs) +ADS_STATUS ads_search(ADS_STRUCT *ads, void **res, + const char *exp, + const char **attrs) { return ads_do_search(ads, ads->bind_path, LDAP_SCOPE_SUBTREE, exp, attrs, res); @@ -99,9 +145,9 @@ int ads_search(ADS_STRUCT *ads, void **res, /* do a search on a specific DistinguishedName */ -int ads_search_dn(ADS_STRUCT *ads, void **res, - const char *dn, - const char **attrs) +ADS_STATUS ads_search_dn(ADS_STRUCT *ads, void **res, + const char *dn, + const char **attrs) { return ads_do_search(ads, dn, LDAP_SCOPE_BASE, "(objectclass=*)", attrs, res); } @@ -118,24 +164,24 @@ void ads_msgfree(ADS_STRUCT *ads, void *msg) /* find a machine account given a hostname */ -int ads_find_machine_acct(ADS_STRUCT *ads, void **res, const char *host) +ADS_STATUS ads_find_machine_acct(ADS_STRUCT *ads, void **res, const char *host) { - int ret; + ADS_STATUS status; char *exp; /* the easiest way to find a machine account anywhere in the tree is to look for hostname$ */ asprintf(&exp, "(samAccountName=%s$)", host); - ret = ads_search(ads, res, exp, NULL); + status = ads_search(ads, res, exp, NULL); free(exp); - return ret; + return status; } /* a convenient routine for adding a generic LDAP record */ -int ads_gen_add(ADS_STRUCT *ads, const char *new_dn, ...) +ADS_STATUS ads_gen_add(ADS_STRUCT *ads, const char *new_dn, ...) { int i; va_list ap; @@ -179,15 +225,16 @@ int ads_gen_add(ADS_STRUCT *ads, const char *new_dn, ...) } free(mods); - return ret; + return ADS_ERROR(ret); } /* add a machine account to the ADS server */ -static int ads_add_machine_acct(ADS_STRUCT *ads, const char *hostname, const char *org_unit) +static ADS_STATUS ads_add_machine_acct(ADS_STRUCT *ads, const char *hostname, + const char *org_unit) { - int ret; + ADS_STATUS ret; char *host_spn, *host_upn, *new_dn, *samAccountName, *controlstr; asprintf(&host_spn, "HOST/%s", hostname); @@ -317,9 +364,9 @@ int ads_count_replies(ADS_STRUCT *ads, void *res) join a machine to a realm, creating the machine account and setting the machine password */ -int ads_join_realm(ADS_STRUCT *ads, const char *hostname, const char *org_unit) +ADS_STATUS ads_join_realm(ADS_STRUCT *ads, const char *hostname, const char *org_unit) { - int rc; + ADS_STATUS status; LDAPMessage *res; char *host; @@ -327,80 +374,78 @@ int ads_join_realm(ADS_STRUCT *ads, const char *hostname, const char *org_unit) host = strdup(hostname); strlower(host); - rc = ads_find_machine_acct(ads, (void **)&res, host); - if (rc == LDAP_SUCCESS && ads_count_replies(ads, res) == 1) { + status = ads_find_machine_acct(ads, (void **)&res, host); + if (ADS_ERR_OK(status) && ads_count_replies(ads, res) == 1) { DEBUG(0, ("Host account for %s already exists\n", host)); - return LDAP_SUCCESS; + return ADS_SUCCESS; } - rc = ads_add_machine_acct(ads, host, org_unit); - if (rc != LDAP_SUCCESS) { - DEBUG(0, ("ads_add_machine_acct: %s\n", ads_errstr(rc))); - return rc; + status = ads_add_machine_acct(ads, host, org_unit); + if (!ADS_ERR_OK(status)) { + DEBUG(0, ("ads_add_machine_acct: %s\n", ads_errstr(status))); + return status; } - rc = ads_find_machine_acct(ads, (void **)&res, host); - if (rc != LDAP_SUCCESS || ads_count_replies(ads, res) != 1) { + status = ads_find_machine_acct(ads, (void **)&res, host); + if (!ADS_ERR_OK(status)) { DEBUG(0, ("Host account test failed\n")); - /* hmmm, we need NTSTATUS */ - return -1; + return status; } free(host); - return LDAP_SUCCESS; + return status; } /* delete a machine from the realm */ -int ads_leave_realm(ADS_STRUCT *ads, const char *hostname) +ADS_STATUS ads_leave_realm(ADS_STRUCT *ads, const char *hostname) { - int rc; + ADS_STATUS status; void *res; char *hostnameDN, *host; + int rc; /* hostname must be lowercase */ host = strdup(hostname); strlower(host); - rc = ads_find_machine_acct(ads, &res, host); - if (rc != LDAP_SUCCESS || ads_count_replies(ads, res) != 1) { + status = ads_find_machine_acct(ads, &res, host); + if (!ADS_ERR_OK(status)) { DEBUG(0, ("Host account for %s does not exist.\n", host)); - return -1; + return status; } hostnameDN = ldap_get_dn(ads->ld, (LDAPMessage *)res); rc = ldap_delete_s(ads->ld, hostnameDN); ldap_memfree(hostnameDN); if (rc != LDAP_SUCCESS) { - DEBUG(0, ("ldap_delete_s: %s\n", ads_errstr(rc))); - return rc; + return ADS_ERROR(rc); } - rc = ads_find_machine_acct(ads, &res, host); - if (rc == LDAP_SUCCESS && ads_count_replies(ads, res) == 1 ) { - DEBUG(0, ("Failed to remove host account.\n")); - /*hmmm, we need NTSTATUS */ - return -1; + status = ads_find_machine_acct(ads, &res, host); + if (ADS_ERR_OK(status) && ads_count_replies(ads, res) == 1) { + DEBUG(0, ("Failed to remove host account.\n")); + return status; } free(host); - return LDAP_SUCCESS; + return status; } -NTSTATUS ads_set_machine_password(ADS_STRUCT *ads, - const char *hostname, - const char *password) +ADS_STATUS ads_set_machine_password(ADS_STRUCT *ads, + const char *hostname, + const char *password) { - NTSTATUS ret; + ADS_STATUS status; char *host = strdup(hostname); strlower(host); - ret = krb5_set_password(ads->kdc_server, host, ads->realm, password); + status = krb5_set_password(ads->kdc_server, host, ads->realm, password); free(host); - return ret; + return status; } /* @@ -510,18 +555,22 @@ int ads_pull_sids(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, /* find the update serial number - this is the core of the ldap cache */ -BOOL ads_USN(ADS_STRUCT *ads, uint32 *usn) +ADS_STATUS ads_USN(ADS_STRUCT *ads, uint32 *usn) { const char *attrs[] = {"highestCommittedUSN", NULL}; - int rc; + ADS_STATUS status; void *res; - BOOL ret; - rc = ads_do_search(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res); - if (rc || ads_count_replies(ads, res) != 1) return False; - ret = ads_pull_uint32(ads, res, "highestCommittedUSN", usn); + status = ads_do_search(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res); + if (!ADS_ERR_OK(status)) return status; + + if (ads_count_replies(ads, res) != 1) { + return ADS_ERROR(LDAP_NO_RESULTS_RETURNED); + } + + ads_pull_uint32(ads, res, "highestCommittedUSN", usn); ads_msgfree(ads, res); - return ret; + return ADS_SUCCESS; } @@ -529,26 +578,25 @@ BOOL ads_USN(ADS_STRUCT *ads, uint32 *usn) The ldapServiceName field on w2k looks like this: vnet3.home.samba.org:win2000-vnet3$@VNET3.HOME.SAMBA.ORG */ -BOOL ads_server_info(ADS_STRUCT *ads) +ADS_STATUS ads_server_info(ADS_STRUCT *ads) { const char *attrs[] = {"ldapServiceName", NULL}; - int rc; + ADS_STATUS status; void *res; char **values; char *p; - rc = ads_do_search(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res); - if (rc || ads_count_replies(ads, res) != 1) return False; + status = ads_do_search(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res); + if (!ADS_ERR_OK(status)) return status; values = ldap_get_values(ads->ld, res, "ldapServiceName"); - - if (!values || !values[0]) return False; + if (!values || !values[0]) return ADS_ERROR(LDAP_NO_RESULTS_RETURNED); p = strchr(values[0], ':'); if (!p) { ldap_value_free(values); ldap_msgfree(res); - return False; + return ADS_ERROR(LDAP_DECODING_ERROR); } SAFE_FREE(ads->ldap_server_name); @@ -559,7 +607,7 @@ BOOL ads_server_info(ADS_STRUCT *ads) ldap_value_free(values); ldap_msgfree(res); SAFE_FREE(ads->ldap_server_name); - return False; + return ADS_ERROR(LDAP_DECODING_ERROR); } *p = 0; @@ -579,35 +627,35 @@ BOOL ads_server_info(ADS_STRUCT *ads) DEBUG(3,("got ldap server name %s@%s\n", ads->ldap_server_name, ads->realm)); - return True; + return ADS_SUCCESS; } /* find the list of trusted domains */ -BOOL ads_trusted_domains(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, - int *num_trusts, char ***names, DOM_SID **sids) +ADS_STATUS ads_trusted_domains(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, + int *num_trusts, char ***names, DOM_SID **sids) { const char *attrs[] = {"flatName", "securityIdentifier", NULL}; - int rc; + ADS_STATUS status; void *res, *msg; int count, i; *num_trusts = 0; - rc = ads_search(ads, &res, "(objectcategory=trustedDomain)", attrs); - if (rc) return False; + status = ads_search(ads, &res, "(objectcategory=trustedDomain)", attrs); + if (!ADS_ERR_OK(status)) return status; count = ads_count_replies(ads, res); if (count == 0) { ads_msgfree(ads, res); - return False; + return ADS_ERROR(LDAP_NO_RESULTS_RETURNED); } (*names) = talloc(mem_ctx, sizeof(char *) * count); (*sids) = talloc(mem_ctx, sizeof(DOM_SID) * count); - if (! *names || ! *sids) return False; + if (! *names || ! *sids) return ADS_ERROR(LDAP_NO_MEMORY); for (i=0, msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) { (*names)[i] = ads_pull_string(ads, mem_ctx, msg, "flatName"); @@ -619,7 +667,7 @@ BOOL ads_trusted_domains(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, *num_trusts = i; - return True; + return ADS_SUCCESS; } #endif diff --git a/source3/libads/sasl.c b/source3/libads/sasl.c index b3610b8fdb..48873252f0 100644 --- a/source3/libads/sasl.c +++ b/source3/libads/sasl.c @@ -53,7 +53,7 @@ static int sasl_interact(LDAP *ld,unsigned flags,void *defaults,void *in) this routine is much less fragile see RFC2078 for details */ -ADS_RETURN_CODE ads_sasl_gssapi_bind(ADS_STRUCT *ads) +ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads) { int minor_status; gss_name_t serv_name; @@ -65,11 +65,11 @@ ADS_RETURN_CODE ads_sasl_gssapi_bind(ADS_STRUCT *ads) struct berval cred; struct berval *scred; int i=0; - int gss_rc; + int gss_rc, rc; uint8 *p; uint32 max_msg_size; char *sname; - ADS_RETURN_CODE rc; + ADS_STATUS status; krb5_principal principal; krb5_context ctx; krb5_enctype enc_types[] = {ENCTYPE_DES_CBC_MD5, ENCTYPE_NULL}; @@ -88,8 +88,10 @@ ADS_RETURN_CODE ads_sasl_gssapi_bind(ADS_STRUCT *ads) input_name.value = &principal; input_name.length = sizeof(principal); - rc.rc = gss_import_name(&minor_status,&input_name,&nt_principal, &serv_name); - rc.error_type = False; + gss_rc = gss_import_name(&minor_status,&input_name,&nt_principal, &serv_name); + if (gss_rc) { + return ADS_ERROR_GSS(gss_rc, minor_status); + } context_handle = GSS_C_NO_CONTEXT; @@ -116,17 +118,19 @@ ADS_RETURN_CODE ads_sasl_gssapi_bind(ADS_STRUCT *ads) } if (gss_rc && gss_rc != GSS_S_CONTINUE_NEEDED) { - rc.minor_status = minor_status; - rc.rc = gss_rc; - rc.error_type = True; - goto failed; + status = ADS_ERROR_GSS(gss_rc, minor_status); + goto failed; } cred.bv_val = output_token.value; cred.bv_len = output_token.length; - rc.rc = ldap_sasl_bind_s(ads->ld, NULL, "GSSAPI", &cred, NULL, NULL, + rc = ldap_sasl_bind_s(ads->ld, NULL, "GSSAPI", &cred, NULL, NULL, &scred); + if (rc != LDAP_SASL_BIND_IN_PROGRESS) { + status = ADS_ERROR(rc); + goto failed; + } if (output_token.value) { gss_release_buffer(&minor_status, &output_token); @@ -140,13 +144,17 @@ ADS_RETURN_CODE ads_sasl_gssapi_bind(ADS_STRUCT *ads) input_token.length = 0; } - if (gss_rc != GSS_S_CONTINUE_NEEDED) break; + if (gss_rc == 0) break; } gss_release_name(&minor_status, &serv_name); gss_rc = gss_unwrap(&minor_status,context_handle,&input_token,&output_token, &conf_state,NULL); + if (gss_rc) { + status = ADS_ERROR_GSS(gss_rc, minor_status); + goto failed; + } gss_release_buffer(&minor_status, &input_token); @@ -169,33 +177,37 @@ ADS_RETURN_CODE ads_sasl_gssapi_bind(ADS_STRUCT *ads) output_token.length = strlen(ads->bind_path) + 8; - rc.rc = gss_wrap(&minor_status, context_handle,0,GSS_C_QOP_DEFAULT, + gss_rc = gss_wrap(&minor_status, context_handle,0,GSS_C_QOP_DEFAULT, &output_token, &conf_state, &input_token); + if (gss_rc) { + status = ADS_ERROR_GSS(gss_rc, minor_status); + goto failed; + } free(output_token.value); cred.bv_val = input_token.value; cred.bv_len = input_token.length; - rc.rc = ldap_sasl_bind_s(ads->ld, NULL, "GSSAPI", &cred, NULL, NULL, + rc = ldap_sasl_bind_s(ads->ld, NULL, "GSSAPI", &cred, NULL, NULL, &scred); + status = ADS_ERROR(rc); gss_release_buffer(&minor_status, &input_token); failed: - return rc; + return status; } -ADS_RETURN_CODE ads_sasl_bind(ADS_STRUCT *ads) +ADS_STATUS ads_sasl_bind(ADS_STRUCT *ads) { #if USE_CYRUS_SASL - ADS_RETURN_CODE rc; - rc.error_type = False; - rc.rc = ldap_sasl_interactive_bind_s(ads->ld, NULL, NULL, NULL, NULL, - LDAP_SASL_QUIET, - sasl_interact, NULL); - return rc; + int rc; + rc = ldap_sasl_interactive_bind_s(ads->ld, NULL, NULL, NULL, NULL, + LDAP_SASL_QUIET, + sasl_interact, NULL); + return ADS_ERROR(rc); #else return ads_sasl_gssapi_bind(ads); #endif diff --git a/source3/nsswitch/winbindd_ads.c b/source3/nsswitch/winbindd_ads.c index c988e697ee..749adafcb6 100644 --- a/source3/nsswitch/winbindd_ads.c +++ b/source3/nsswitch/winbindd_ads.c @@ -32,64 +32,61 @@ static char *primary_realm; a wrapper around ldap_search_s that retries depending on the error code this is supposed to catch dropped connections and auto-reconnect */ -int ads_do_search_retry(ADS_STRUCT *ads, const char *bind_path, int scope, - const char *exp, - const char **attrs, void **res) +ADS_STATUS ads_do_search_retry(ADS_STRUCT *ads, const char *bind_path, int scope, + const char *exp, + const char **attrs, void **res) { - int rc = -1; - ADS_RETURN_CODE rc2; + ADS_STATUS status; int count = 3; if (!ads->ld && time(NULL) - ads->last_attempt < ADS_RECONNECT_TIME) { - return LDAP_SERVER_DOWN; + return ADS_ERROR(LDAP_SERVER_DOWN); } while (count--) { - rc = ads_do_search(ads, bind_path, scope, exp, attrs, res); - if (rc == 0) { + status = ads_do_search(ads, bind_path, scope, exp, attrs, res); + if (ADS_ERR_OK(status)) { DEBUG(5,("Search for %s gave %d replies\n", exp, ads_count_replies(ads, *res))); - return rc; + return status; } if (*res) ads_msgfree(ads, *res); *res = NULL; - DEBUG(1,("Reopening ads connection after error %s\n", ads_errstr(rc))); + DEBUG(1,("Reopening ads connection after error %s\n", + ads_errstr(status))); if (ads->ld) { /* we should unbind here, but that seems to trigger openldap bugs :( ldap_unbind(ads->ld); */ } ads->ld = NULL; - rc2 = ads_connect(ads); - if (rc2.rc) { - DEBUG(1,("ads_search_retry: failed to reconnect:\n")); - if(rc2.error_type) - ads_display_status("", rc2.rc, rc2.minor_status); - else - DEBUG(1,("LDAP error: %s\n", ads_errstr(rc2.rc))); - - ads_destroy(&ads); - return rc2.rc; + status = ads_connect(ads); + if (!ADS_ERR_OK(status)) { + DEBUG(1,("ads_search_retry: failed to reconnect (%s)\n", + ads_errstr(status))); + ads_destroy(&ads); + return status; } } - DEBUG(1,("ads reopen failed after error %s\n", ads_errstr(rc))); - return rc; + + DEBUG(1,("ads reopen failed after error %s\n", ads_errstr(status))); + return status; } -int ads_search_retry(ADS_STRUCT *ads, void **res, - const char *exp, - const char **attrs) +ADS_STATUS ads_search_retry(ADS_STRUCT *ads, void **res, + const char *exp, + const char **attrs) { return ads_do_search_retry(ads, ads->bind_path, LDAP_SCOPE_SUBTREE, exp, attrs, res); } -int ads_search_retry_dn(ADS_STRUCT *ads, void **res, - const char *dn, - const char **attrs) +ADS_STATUS ads_search_retry_dn(ADS_STRUCT *ads, void **res, + const char *dn, + const char **attrs) { return ads_do_search_retry(ads, dn, LDAP_SCOPE_BASE, "(objectclass=*)", attrs, res); @@ -102,7 +99,7 @@ int ads_search_retry_dn(ADS_STRUCT *ads, void **res, static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain) { ADS_STRUCT *ads; - ADS_RETURN_CODE rc; + ADS_STATUS status; char *ccache; struct in_addr server_ip; @@ -130,14 +127,10 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain) SAFE_FREE(ads->password); ads->password = secrets_fetch_machine_password(); - rc = ads_connect(ads); - if (rc.rc) { - DEBUG(1,("ads_connect for domain %s failed:\n", domain->name)); - if(rc.error_type) - ads_display_status("", rc.rc, rc.minor_status); - else - DEBUG(1,("LDAP error: %s\n", ads_errstr(rc.rc))); - + status = ads_connect(ads); + if (!ADS_ERR_OK(status)) { + DEBUG(1,("ads_connect for domain %s failed: %s\n", + domain->name, ads_errstr(status))); ads_destroy(&ads); return NULL; } @@ -183,7 +176,8 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain, ADS_STRUCT *ads = NULL; const char *attrs[] = {"sAMAccountName", "name", "objectSid", "primaryGroupID", "sAMAccountType", NULL}; - int rc, i, count; + int i, count; + ADS_STATUS rc; void *res = NULL; void *msg = NULL; NTSTATUS status = NT_STATUS_UNSUCCESSFUL; @@ -196,7 +190,7 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain, if (!ads) goto done; rc = ads_search_retry(ads, &res, "(objectCategory=user)", attrs); - if (rc) { + if (!ADS_ERR_OK(rc)) { DEBUG(1,("query_user_list ads_search: %s\n", ads_errstr(rc))); goto done; } @@ -270,7 +264,8 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, ADS_STRUCT *ads = NULL; const char *attrs[] = {"sAMAccountName", "name", "objectSid", "sAMAccountType", NULL}; - int rc, i, count; + int i, count; + ADS_STATUS rc; void *res = NULL; void *msg = NULL; NTSTATUS status = NT_STATUS_UNSUCCESSFUL; @@ -283,7 +278,7 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, if (!ads) goto done; rc = ads_search_retry(ads, &res, "(objectCategory=group)", attrs); - if (rc) { + if (!ADS_ERR_OK(rc)) { DEBUG(1,("query_user_list ads_search: %s\n", ads_errstr(rc))); goto done; } @@ -351,7 +346,8 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain, { ADS_STRUCT *ads = NULL; const char *attrs[] = {"objectSid", "sAMAccountType", NULL}; - int rc, count; + int count; + ADS_STATUS rc; void *res = NULL; char *exp; uint32 t; @@ -373,7 +369,7 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain, asprintf(&exp, "(sAMAccountName=%s)", name2); rc = ads_search_retry(ads, &res, exp, attrs); free(exp); - if (rc) { + if (!ADS_ERR_OK(rc)) { DEBUG(1,("name_to_sid ads_search: %s\n", ads_errstr(rc))); goto done; } @@ -415,7 +411,7 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain, { ADS_STRUCT *ads = NULL; const char *attrs[] = {"sAMAccountName", "sAMAccountType", NULL}; - int rc; + ADS_STATUS rc; void *msg = NULL; char *exp; char *sidstr; @@ -433,7 +429,7 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain, rc = ads_search_retry(ads, &msg, exp, attrs); free(exp); free(sidstr); - if (rc) { + if (!ADS_ERR_OK(rc)) { DEBUG(1,("sid_to_name ads_search: %s\n", ads_errstr(rc))); goto done; } @@ -466,7 +462,8 @@ static NTSTATUS query_user(struct winbindd_domain *domain, ADS_STRUCT *ads = NULL; const char *attrs[] = {"sAMAccountName", "name", "objectSid", "primaryGroupID", NULL}; - int rc, count; + ADS_STATUS rc; + int count; void *msg = NULL; char *exp; DOM_SID sid; @@ -485,7 +482,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain, rc = ads_search_retry(ads, &msg, exp, attrs); free(exp); free(sidstr); - if (rc) { + if (!ADS_ERR_OK(rc)) { DEBUG(1,("query_user(rid=%d) ads_search: %s\n", user_rid, ads_errstr(rc))); goto done; } @@ -531,7 +528,8 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, ADS_STRUCT *ads = NULL; const char *attrs[] = {"distinguishedName", NULL}; const char *attrs2[] = {"tokenGroups", "primaryGroupID", NULL}; - int rc, count; + ADS_STATUS rc; + int count; void *msg = NULL; char *exp; char *user_dn; @@ -558,7 +556,7 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, rc = ads_search_retry(ads, &msg, exp, attrs); free(exp); free(sidstr); - if (rc) { + if (!ADS_ERR_OK(rc)) { DEBUG(1,("lookup_usergroups(rid=%d) ads_search: %s\n", user_rid, ads_errstr(rc))); goto done; } @@ -568,7 +566,7 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, if (msg) ads_msgfree(ads, msg); rc = ads_search_retry_dn(ads, &msg, user_dn, attrs2); - if (rc) { + if (!ADS_ERR_OK(rc)) { DEBUG(1,("lookup_usergroups(rid=%d) ads_search tokenGroups: %s\n", user_rid, ads_errstr(rc))); goto done; } @@ -607,7 +605,8 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, DOM_SID group_sid; char *sidstr; const char *attrs[] = {"sAMAccountName", "objectSid", "sAMAccountType", NULL}; - int rc, count; + ADS_STATUS rc; + int count; void *res=NULL, *msg=NULL; ADS_STRUCT *ads = NULL; char *exp; @@ -626,7 +625,7 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, rc = ads_search_retry(ads, &res, exp, attrs); free(exp); free(sidstr); - if (rc) { + if (!ADS_ERR_OK(rc)) { DEBUG(1,("query_user_list ads_search: %s\n", ads_errstr(rc))); goto done; } @@ -674,17 +673,15 @@ done: static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq) { ADS_STRUCT *ads = NULL; + ADS_STATUS rc; *seq = DOM_SEQUENCE_NONE; ads = ads_cached_connection(domain); if (!ads) return NT_STATUS_UNSUCCESSFUL; - if (!ads_USN(ads, seq)) { - return NT_STATUS_UNSUCCESSFUL; - } - - return NT_STATUS_OK; + rc = ads_USN(ads, seq); + return ads_ntstatus(rc); } /* get a list of trusted domains */ @@ -695,6 +692,7 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, DOM_SID **dom_sids) { ADS_STRUCT *ads = NULL; + ADS_STATUS rc; *num_domains = 0; *names = NULL; @@ -702,11 +700,9 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, ads = ads_cached_connection(domain); if (!ads) return NT_STATUS_UNSUCCESSFUL; - if (!ads_trusted_domains(ads, mem_ctx, num_domains, names, dom_sids)) { - return NT_STATUS_UNSUCCESSFUL; - } + rc = ads_trusted_domains(ads, mem_ctx, num_domains, names, dom_sids); - return NT_STATUS_OK; + return ads_ntstatus(rc); } /* find the domain sid for a domain */ @@ -716,14 +712,14 @@ static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid) const char *attrs[] = {"objectSid", NULL}; ADS_STRUCT *ads = NULL; void *res; - int rc; + ADS_STATUS rc; ads = ads_cached_connection(domain); if (!ads) goto done; rc = ads_do_search(ads, ads->bind_path, LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res); - if (rc) goto done; + if (!ADS_ERR_OK(rc)) goto done; if (ads_pull_sid(ads, res, "objectSid", sid)) { status = NT_STATUS_OK; } diff --git a/source3/nsswitch/winbindd_proto.h b/source3/nsswitch/winbindd_proto.h index d50469d978..f0badc4331 100644 --- a/source3/nsswitch/winbindd_proto.h +++ b/source3/nsswitch/winbindd_proto.h @@ -9,15 +9,15 @@ int main(int argc, char **argv); /* The following definitions come from nsswitch/winbindd_ads.c */ -int ads_do_search_retry(ADS_STRUCT *ads, const char *bind_path, int scope, - const char *exp, - const char **attrs, void **res); -int ads_search_retry(ADS_STRUCT *ads, void **res, - const char *exp, - const char **attrs); -int ads_search_retry_dn(ADS_STRUCT *ads, void **res, - const char *dn, - const char **attrs); +ADS_STATUS ads_do_search_retry(ADS_STRUCT *ads, const char *bind_path, int scope, + const char *exp, + const char **attrs, void **res); +ADS_STATUS ads_search_retry(ADS_STRUCT *ads, void **res, + const char *exp, + const char **attrs); +ADS_STATUS ads_search_retry_dn(ADS_STRUCT *ads, void **res, + const char *dn, + const char **attrs); /* The following definitions come from nsswitch/winbindd_cache.c */ diff --git a/source3/script/mkproto.awk b/source3/script/mkproto.awk index 7c8bc3d6cf..36f5b0afd1 100644 --- a/source3/script/mkproto.awk +++ b/source3/script/mkproto.awk @@ -122,7 +122,7 @@ END { gotstart = 1; } - if( $0 ~ /^ADS_STRUCT|^ADS_RETURN_CODE|^DATA_BLOB|^ASN1_DATA|^TDB_CONTEXT|^TDB_DATA|^smb_ucs2_t|^TALLOC_CTX|^hash_element|^NT_DEVICEMODE|^enum.*\(|^NT_USER_TOKEN|^SAM_ACCOUNT/ ) { + if( $0 ~ /^ADS_STRUCT|^ADS_STATUS|^DATA_BLOB|^ASN1_DATA|^TDB_CONTEXT|^TDB_DATA|^smb_ucs2_t|^TALLOC_CTX|^hash_element|^NT_DEVICEMODE|^enum.*\(|^NT_USER_TOKEN|^SAM_ACCOUNT/ ) { gotstart = 1; } diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c index 0d7b641771..3bfc9d935c 100644 --- a/source3/utils/net_ads.c +++ b/source3/utils/net_ads.c @@ -68,7 +68,7 @@ static int net_ads_info(int argc, const char **argv) static ADS_STRUCT *ads_startup(void) { ADS_STRUCT *ads; - ADS_RETURN_CODE rc; + ADS_STATUS status; extern char *opt_password; extern char *opt_user_name; @@ -87,12 +87,9 @@ static ADS_STRUCT *ads_startup(void) ads->password = strdup(opt_password); ads->user_name = strdup(opt_user_name); - rc = ads_connect(ads); - if (rc.rc) { - if(rc.error_type) - ads_display_status("ads_connect", rc.rc, rc.minor_status); - else - d_printf("ads_connect: %s\n", ads_errstr(rc.rc)); + status = ads_connect(ads); + if (!ADS_ERR_OK(status)) { + d_printf("ads_connect: %s\n", ads_errstr(status)); return NULL; } return ads; @@ -101,13 +98,13 @@ static ADS_STRUCT *ads_startup(void) static int net_ads_user(int argc, const char **argv) { ADS_STRUCT *ads; - int rc; + ADS_STATUS rc; void *res; const char *attrs[] = {"sAMAccountName", "name", "objectSid", NULL}; if (!(ads = ads_startup())) return -1; rc = ads_search(ads, &res, "(objectclass=user)", attrs); - if (rc) { + if (!ADS_ERR_OK(rc)) { d_printf("ads_search: %s\n", ads_errstr(rc)); return -1; } @@ -125,13 +122,13 @@ static int net_ads_user(int argc, const char **argv) static int net_ads_group(int argc, const char **argv) { ADS_STRUCT *ads; - int rc; + ADS_STATUS rc; void *res; const char *attrs[] = {"sAMAccountName", "name", "objectSid", NULL}; if (!(ads = ads_startup())) return -1; rc = ads_search(ads, &res, "(objectclass=group)", attrs); - if (rc) { + if (!ADS_ERR_OK(rc)) { d_printf("ads_search: %s\n", ads_errstr(rc)); return -1; } @@ -148,14 +145,14 @@ static int net_ads_group(int argc, const char **argv) static int net_ads_status(int argc, const char **argv) { ADS_STRUCT *ads; - int rc; + ADS_STATUS rc; extern pstring global_myname; void *res; if (!(ads = ads_startup())) return -1; rc = ads_find_machine_acct(ads, &res, global_myname); - if (rc) { + if (!ADS_ERR_OK(rc)) { d_printf("ads_find_machine_acct: %s\n", ads_errstr(rc)); return -1; } @@ -173,7 +170,7 @@ static int net_ads_status(int argc, const char **argv) static int net_ads_leave(int argc, const char **argv) { ADS_STRUCT *ads = NULL; - int rc; + ADS_STATUS rc; extern pstring global_myname; if (!(ads = ads_startup())) { @@ -186,7 +183,7 @@ static int net_ads_leave(int argc, const char **argv) } rc = ads_leave_realm(ads, global_myname); - if (rc) { + if (!ADS_ERR_OK(rc)) { d_printf("Failed to delete host '%s' from the '%s' realm.\n", global_myname, ads->realm); return -1; @@ -200,11 +197,10 @@ static int net_ads_leave(int argc, const char **argv) static int net_ads_join(int argc, const char **argv) { ADS_STRUCT *ads; - int rc; + ADS_STATUS rc; char *password; char *tmp_password; extern pstring global_myname; - NTSTATUS status; const char *org_unit = "Computers"; char *dn; void *res; @@ -227,25 +223,25 @@ static int net_ads_join(int argc, const char **argv) free(dn); ads_msgfree(ads, res); - if (rc == LDAP_NO_SUCH_OBJECT) { + if (rc.error_type == ADS_ERROR_LDAP && rc.rc == LDAP_NO_SUCH_OBJECT) { d_printf("ads_join_realm: organisational unit %s does not exist\n", org_unit); - return rc; + return -1; } - if (rc) { + if (!ADS_ERR_OK(rc)) { d_printf("ads_join_realm: %s\n", ads_errstr(rc)); return -1; } rc = ads_join_realm(ads, global_myname, org_unit); - if (rc) { + if (!ADS_ERR_OK(rc)) { d_printf("ads_join_realm: %s\n", ads_errstr(rc)); return -1; } - status = ads_set_machine_password(ads, global_myname, password); - if (!NT_STATUS_IS_OK(status)) { - d_printf("ads_set_machine_password: %s\n", get_nt_error_msg(status)); + rc = ads_set_machine_password(ads, global_myname, password); + if (!ADS_ERR_OK(rc)) { + d_printf("ads_set_machine_password: %s\n", ads_errstr(rc)); return -1; } -- cgit