summaryrefslogtreecommitdiff
path: root/source3/lib
diff options
context:
space:
mode:
Diffstat (limited to 'source3/lib')
-rw-r--r--source3/lib/ads_flags.c150
-rw-r--r--source3/lib/smbldap.c133
-rw-r--r--source3/lib/util.c33
-rw-r--r--source3/lib/wb_reqtrans.c429
-rw-r--r--source3/lib/wbclient.c674
5 files changed, 225 insertions, 1194 deletions
diff --git a/source3/lib/ads_flags.c b/source3/lib/ads_flags.c
new file mode 100644
index 0000000000..a8fa062f2a
--- /dev/null
+++ b/source3/lib/ads_flags.c
@@ -0,0 +1,150 @@
+/*
+ Unix SMB/CIFS implementation.
+ ads (active directory) utility library
+
+ Copyright (C) Stefan (metze) Metzmacher 2002
+ Copyright (C) Andrew Tridgell 2001
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+
+/*
+translated the ACB_CTRL Flags to UserFlags (userAccountControl)
+*/
+uint32 ads_acb2uf(uint32 acb)
+{
+ uint32 uf = 0x00000000;
+
+ if (acb & ACB_DISABLED) uf |= UF_ACCOUNTDISABLE;
+ if (acb & ACB_HOMDIRREQ) uf |= UF_HOMEDIR_REQUIRED;
+ if (acb & ACB_PWNOTREQ) uf |= UF_PASSWD_NOTREQD;
+ if (acb & ACB_TEMPDUP) uf |= UF_TEMP_DUPLICATE_ACCOUNT;
+ if (acb & ACB_NORMAL) uf |= UF_NORMAL_ACCOUNT;
+ if (acb & ACB_MNS) uf |= UF_MNS_LOGON_ACCOUNT;
+ if (acb & ACB_DOMTRUST) uf |= UF_INTERDOMAIN_TRUST_ACCOUNT;
+ if (acb & ACB_WSTRUST) uf |= UF_WORKSTATION_TRUST_ACCOUNT;
+ if (acb & ACB_SVRTRUST) uf |= UF_SERVER_TRUST_ACCOUNT;
+ if (acb & ACB_PWNOEXP) uf |= UF_DONT_EXPIRE_PASSWD;
+ if (acb & ACB_AUTOLOCK) uf |= UF_LOCKOUT;
+ if (acb & ACB_USE_DES_KEY_ONLY) uf |= UF_USE_DES_KEY_ONLY;
+ if (acb & ACB_SMARTCARD_REQUIRED) uf |= UF_SMARTCARD_REQUIRED;
+ if (acb & ACB_TRUSTED_FOR_DELEGATION) uf |= UF_TRUSTED_FOR_DELEGATION;
+ if (acb & ACB_DONT_REQUIRE_PREAUTH) uf |= UF_DONT_REQUIRE_PREAUTH;
+ if (acb & ACB_NO_AUTH_DATA_REQD) uf |= UF_NO_AUTH_DATA_REQUIRED;
+ if (acb & ACB_NOT_DELEGATED) uf |= UF_NOT_DELEGATED;
+ if (acb & ACB_ENC_TXT_PWD_ALLOWED) uf |= UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED;
+
+ return uf;
+}
+
+/*
+translated the UserFlags (userAccountControl) to ACB_CTRL Flags
+*/
+uint32 ads_uf2acb(uint32 uf)
+{
+ uint32 acb = 0x00000000;
+
+ if (uf & UF_ACCOUNTDISABLE) acb |= ACB_DISABLED;
+ if (uf & UF_HOMEDIR_REQUIRED) acb |= ACB_HOMDIRREQ;
+ if (uf & UF_PASSWD_NOTREQD) acb |= ACB_PWNOTREQ;
+ if (uf & UF_MNS_LOGON_ACCOUNT) acb |= ACB_MNS;
+ if (uf & UF_DONT_EXPIRE_PASSWD) acb |= ACB_PWNOEXP;
+ if (uf & UF_LOCKOUT) acb |= ACB_AUTOLOCK;
+ if (uf & UF_USE_DES_KEY_ONLY) acb |= ACB_USE_DES_KEY_ONLY;
+ if (uf & UF_SMARTCARD_REQUIRED) acb |= ACB_SMARTCARD_REQUIRED;
+ if (uf & UF_TRUSTED_FOR_DELEGATION) acb |= ACB_TRUSTED_FOR_DELEGATION;
+ if (uf & UF_DONT_REQUIRE_PREAUTH) acb |= ACB_DONT_REQUIRE_PREAUTH;
+ if (uf & UF_NO_AUTH_DATA_REQUIRED) acb |= ACB_NO_AUTH_DATA_REQD;
+ if (uf & UF_NOT_DELEGATED) acb |= ACB_NOT_DELEGATED;
+ if (uf & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED) acb |= ACB_ENC_TXT_PWD_ALLOWED;
+
+ switch (uf & UF_ACCOUNT_TYPE_MASK)
+ {
+ case UF_TEMP_DUPLICATE_ACCOUNT: acb |= ACB_TEMPDUP;break;
+ case UF_NORMAL_ACCOUNT: acb |= ACB_NORMAL;break;
+ case UF_INTERDOMAIN_TRUST_ACCOUNT: acb |= ACB_DOMTRUST;break;
+ case UF_WORKSTATION_TRUST_ACCOUNT: acb |= ACB_WSTRUST;break;
+ case UF_SERVER_TRUST_ACCOUNT: acb |= ACB_SVRTRUST;break;
+ /*Fix Me: what should we do here? */
+ default: acb |= ACB_NORMAL;break;
+ }
+
+ return acb;
+}
+
+/*
+get the accountType from the UserFlags
+*/
+uint32 ads_uf2atype(uint32 uf)
+{
+ uint32 atype = 0x00000000;
+
+ if (uf & UF_NORMAL_ACCOUNT) atype = ATYPE_NORMAL_ACCOUNT;
+ else if (uf & UF_TEMP_DUPLICATE_ACCOUNT) atype = ATYPE_NORMAL_ACCOUNT;
+ else if (uf & UF_SERVER_TRUST_ACCOUNT) atype = ATYPE_WORKSTATION_TRUST;
+ else if (uf & UF_WORKSTATION_TRUST_ACCOUNT) atype = ATYPE_WORKSTATION_TRUST;
+ else if (uf & UF_INTERDOMAIN_TRUST_ACCOUNT) atype = ATYPE_INTERDOMAIN_TRUST;
+
+ return atype;
+}
+
+/*
+get the accountType from the groupType
+*/
+uint32 ads_gtype2atype(uint32 gtype)
+{
+ uint32 atype = 0x00000000;
+
+ switch(gtype) {
+ case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP:
+ atype = ATYPE_SECURITY_LOCAL_GROUP;
+ break;
+ case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP:
+ atype = ATYPE_SECURITY_LOCAL_GROUP;
+ break;
+ case GTYPE_SECURITY_GLOBAL_GROUP:
+ atype = ATYPE_SECURITY_GLOBAL_GROUP;
+ break;
+
+ case GTYPE_DISTRIBUTION_GLOBAL_GROUP:
+ atype = ATYPE_DISTRIBUTION_GLOBAL_GROUP;
+ break;
+ case GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP:
+ atype = ATYPE_DISTRIBUTION_UNIVERSAL_GROUP;
+ break;
+ case GTYPE_DISTRIBUTION_UNIVERSAL_GROUP:
+ atype = ATYPE_DISTRIBUTION_LOCAL_GROUP;
+ break;
+ }
+
+ return atype;
+}
+
+/* turn a sAMAccountType into a SID_NAME_USE */
+enum lsa_SidType ads_atype_map(uint32 atype)
+{
+ switch (atype & 0xF0000000) {
+ case ATYPE_GLOBAL_GROUP:
+ return SID_NAME_DOM_GRP;
+ case ATYPE_SECURITY_LOCAL_GROUP:
+ return SID_NAME_ALIAS;
+ case ATYPE_ACCOUNT:
+ return SID_NAME_USER;
+ default:
+ DEBUG(1,("hmm, need to map account type 0x%x\n", atype));
+ }
+ return SID_NAME_UNKNOWN;
+}
diff --git a/source3/lib/smbldap.c b/source3/lib/smbldap.c
index b6921c329c..4833b96c5f 100644
--- a/source3/lib/smbldap.c
+++ b/source3/lib/smbldap.c
@@ -6,20 +6,20 @@
Copyright (C) Shahms King 2001
Copyright (C) Andrew Bartlett 2002-2003
Copyright (C) Stefan (metze) Metzmacher 2002-2003
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-
+
*/
#include "includes.h"
@@ -217,13 +217,13 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = {
const char* get_attr_key2string( ATTRIB_MAP_ENTRY table[], int key )
{
int i = 0;
-
+
while ( table[i].attrib != LDAP_ATTR_LIST_END ) {
if ( table[i].attrib == key )
return table[i].name;
i++;
}
-
+
return NULL;
}
@@ -236,7 +236,7 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = {
{
const char **names;
int i = 0;
-
+
while ( table[i].attrib != LDAP_ATTR_LIST_END )
i++;
i++;
@@ -253,7 +253,7 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = {
i++;
}
names[i] = NULL;
-
+
return names;
}
@@ -266,25 +266,25 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = {
int max_len)
{
char **values;
-
+
if ( !attribute )
return False;
-
+
value[0] = '\0';
if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) {
DEBUG (10, ("smbldap_get_single_attribute: [%s] = [<does not exist>]\n", attribute));
-
+
return False;
}
-
+
if (convert_string(CH_UTF8, CH_UNIX,values[0], -1, value, max_len, False) == (size_t)-1) {
DEBUG(1, ("smbldap_get_single_attribute: string conversion of [%s] = [%s] failed!\n",
attribute, values[0]));
ldap_value_free(values);
return False;
}
-
+
ldap_value_free(values);
#ifdef DEBUG_PASSWORDS
DEBUG (100, ("smbldap_get_single_attribute: [%s] = [%s]\n", attribute, value));
@@ -389,23 +389,42 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = {
return result;
}
- bool smbldap_pull_sid(LDAP *ld, LDAPMessage *msg, const char *attrib,
- struct dom_sid *sid)
+ bool smbldap_talloc_single_blob(TALLOC_CTX *mem_ctx, LDAP *ld,
+ LDAPMessage *msg, const char *attrib,
+ DATA_BLOB *blob)
{
struct berval **values;
- bool ret = False;
values = ldap_get_values_len(ld, msg, attrib);
-
if (!values) {
return false;
}
- if (values[0] != NULL) {
- ret = sid_parse(values[0]->bv_val, values[0]->bv_len, sid);
+ if (ldap_count_values_len(values) != 1) {
+ DEBUG(10, ("Expected one value for %s, got %d\n", attrib,
+ ldap_count_values_len(values)));
+ return false;
}
+ *blob = data_blob_talloc(mem_ctx, values[0]->bv_val,
+ values[0]->bv_len);
ldap_value_free_len(values);
+
+ return (blob->data != NULL);
+}
+
+ bool smbldap_pull_sid(LDAP *ld, LDAPMessage *msg, const char *attrib,
+ struct dom_sid *sid)
+{
+ DATA_BLOB blob;
+ bool ret;
+
+ if (!smbldap_talloc_single_blob(talloc_tos(), ld, msg, attrib,
+ &blob)) {
+ return false;
+ }
+ ret = sid_parse((char *)blob.data, blob.length, sid);
+ TALLOC_FREE(blob.data);
return ret;
}
@@ -514,7 +533,7 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = {
for (; mods[i]->mod_values[j] != NULL; j++);
}
mods[i]->mod_values = SMB_REALLOC_ARRAY(mods[i]->mod_values, char *, j + 2);
-
+
if (mods[i]->mod_values == NULL) {
smb_panic("smbldap_set_mod: out of memory!");
/* notreached. */
@@ -524,8 +543,7 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = {
smb_panic("smbldap_set_mod: String conversion failure!");
/* notreached. */
}
-
-
+
mods[i]->mod_values[j] = SMB_STRDUP(utf8_value);
TALLOC_FREE(utf8_value);
SMB_ASSERT(mods[i]->mod_values[j] != NULL);
@@ -561,9 +579,9 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = {
}
/* all of our string attributes are case insensitive */
-
+
if (existed && newval && (StrCaseCmp(oldval, newval) == 0)) {
-
+
/* Believe it or not, but LDAP will deny a delete and
an add at the same time if the values are the
same... */
@@ -582,7 +600,7 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = {
/* This will also allow modifying single valued attributes
* in Novell NDS. In NDS you have to first remove attribute and then
* you could add new value */
-
+
DEBUG(10,("smbldap_make_mod: deleting attribute |%s| values |%s|\n", attribute, oldval));
smbldap_set_mod(mods, LDAP_MOD_DELETE, attribute, oldval);
}
@@ -640,7 +658,7 @@ static void smbldap_store_state(LDAP *ld, struct smbldap_state *smbldap_state)
{
struct smbldap_state *tmp_ldap_state;
struct smbldap_state_lookup *t;
-
+
if ((tmp_ldap_state = smbldap_find_state(ld))) {
SMB_ASSERT(tmp_ldap_state == smbldap_state);
return;
@@ -648,7 +666,7 @@ static void smbldap_store_state(LDAP *ld, struct smbldap_state *smbldap_state)
t = SMB_XMALLOC_P(struct smbldap_state_lookup);
ZERO_STRUCTP(t);
-
+
DLIST_ADD_END(smbldap_state_lookup_list, t, struct smbldap_state_lookup *);
t->ld = ld;
t->smbldap_state = smbldap_state;
@@ -663,11 +681,11 @@ int smb_ldap_start_tls(LDAP *ldap_struct, int version)
#ifdef LDAP_OPT_X_TLS
int rc;
#endif
-
+
if (lp_ldap_ssl() != LDAP_SSL_START_TLS) {
return LDAP_SUCCESS;
}
-
+
#ifdef LDAP_OPT_X_TLS
if (version != LDAP_VERSION3) {
DEBUG(0, ("Need LDAPv3 for Start TLS\n"));
@@ -697,9 +715,9 @@ int smb_ldap_setup_conn(LDAP **ldap_struct, const char *uri)
int rc;
DEBUG(10, ("smb_ldap_setup_connection: %s\n", uri));
-
+
#ifdef HAVE_LDAP_INITIALIZE
-
+
rc = ldap_initialize(ldap_struct, uri);
if (rc) {
DEBUG(0, ("ldap_initialize: %s\n", ldap_err2string(rc)));
@@ -721,9 +739,9 @@ int smb_ldap_setup_conn(LDAP **ldap_struct, const char *uri)
if ( strnequal( uri, "URL:", 4 ) ) {
uri += 4;
}
-
+
sscanf(uri, "%10[^:]://%254[^:/]:%d", protocol, host, &port);
-
+
if (port == 0) {
if (strequal(protocol, "ldap")) {
port = LDAP_PORT;
@@ -733,12 +751,12 @@ int smb_ldap_setup_conn(LDAP **ldap_struct, const char *uri)
DEBUG(0, ("unrecognised protocol (%s)!\n", protocol));
}
}
-
+
if ((*ldap_struct = ldap_init(host, port)) == NULL) {
DEBUG(0, ("ldap_init failed !\n"));
return LDAP_OPERATIONS_ERROR;
}
-
+
if (strequal(protocol, "ldaps")) {
#ifdef LDAP_OPT_X_TLS
int tls = LDAP_OPT_X_TLS_HARD;
@@ -746,7 +764,7 @@ int smb_ldap_setup_conn(LDAP **ldap_struct, const char *uri)
{
DEBUG(0, ("Failed to setup a TLS session\n"));
}
-
+
DEBUG(3,("LDAPS option set...!\n"));
#else
DEBUG(0,("smbldap_open_connection: Secure connection not supported by LDAP client libraries!\n"));
@@ -792,7 +810,7 @@ int smb_ldap_upgrade_conn(LDAP *ldap_struct, int *new_version)
{
int version;
int rc;
-
+
/* assume the worst */
*new_version = LDAP_VERSION2;
@@ -812,7 +830,7 @@ int smb_ldap_upgrade_conn(LDAP *ldap_struct, int *new_version)
if (rc) {
return rc;
}
-
+
*new_version = LDAP_VERSION3;
return LDAP_SUCCESS;
}
@@ -875,7 +893,7 @@ static int smbldap_open_connection (struct smbldap_state *ldap_state)
if (rc) {
return rc;
}
-
+
DEBUG(2, ("smbldap_open_connection: connection opened\n"));
return rc;
}
@@ -890,11 +908,11 @@ static int rebindproc_with_state (LDAP * ld, char **whop, char **credp,
int *methodp, int freeit, void *arg)
{
struct smbldap_state *ldap_state = arg;
-
+
/** @TODO Should we be doing something to check what servers we rebind to?
Could we get a referral to a machine that we don't want to give our
username and password to? */
-
+
if (freeit) {
SAFE_FREE(*whop);
if (*credp) {
@@ -923,7 +941,7 @@ static int rebindproc_with_state (LDAP * ld, char **whop, char **credp,
}
GetTimeOfDay(&ldap_state->last_rebind);
-
+
return 0;
}
#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
@@ -998,7 +1016,6 @@ static int rebindproc (LDAP *ldap_struct, char **whop, char **credp,
return rebindproc_with_state(ldap_struct, whop, credp,
method, freeit, ldap_state);
-
}
# endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
@@ -1039,7 +1056,7 @@ static int smbldap_connect_system(struct smbldap_state *ldap_state, LDAP * ldap_
/* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite
(OpenLDAP) doesnt' seem to support it */
-
+
DEBUG(10,("ldap_connect_system: Binding to ldap server %s as \"%s\"\n",
ldap_state->uri, ldap_state->bind_dn));
@@ -1175,17 +1192,17 @@ static NTSTATUS smbldap_close(struct smbldap_state *ldap_state)
{
if (!ldap_state)
return NT_STATUS_INVALID_PARAMETER;
-
+
if (ldap_state->ldap_struct != NULL) {
ldap_unbind(ldap_state->ldap_struct);
ldap_state->ldap_struct = NULL;
}
smbldap_delete_state(ldap_state);
-
+
DEBUG(5,("The connection to the LDAP server was closed\n"));
/* maybe free the results here --metze */
-
+
return NT_STATUS_OK;
}
@@ -1279,7 +1296,7 @@ static int smbldap_search_ext(struct smbldap_state *ldap_state,
size_t converted_size;
SMB_ASSERT(ldap_state);
-
+
DEBUG(5,("smbldap_search_ext: base => [%s], filter => [%s], "
"scope => [%d]\n", base, filter, scope));
@@ -1506,7 +1523,7 @@ int smbldap_modify(struct smbldap_state *ldap_state, const char *dn, LDAPMod *at
}
}
}
-
+
TALLOC_FREE(utf8_dn);
return rc;
}
@@ -1518,7 +1535,7 @@ int smbldap_add(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs
char *utf8_dn;
time_t endtime = time(NULL)+lp_ldap_timeout();
size_t converted_size;
-
+
SMB_ASSERT(ldap_state);
DEBUG(5,("smbldap_add: dn => [%s]\n", dn ));
@@ -1550,7 +1567,7 @@ int smbldap_add(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs
}
}
}
-
+
TALLOC_FREE(utf8_dn);
return rc;
}
@@ -1562,7 +1579,7 @@ int smbldap_delete(struct smbldap_state *ldap_state, const char *dn)
char *utf8_dn;
time_t endtime = time(NULL)+lp_ldap_timeout();
size_t converted_size;
-
+
SMB_ASSERT(ldap_state);
DEBUG(5,("smbldap_delete: dn => [%s]\n", dn ));
@@ -1594,7 +1611,7 @@ int smbldap_delete(struct smbldap_state *ldap_state, const char *dn)
}
}
}
-
+
TALLOC_FREE(utf8_dn);
return rc;
}
@@ -1607,7 +1624,7 @@ int smbldap_extended_operation(struct smbldap_state *ldap_state,
int rc = LDAP_SERVER_DOWN;
int attempts = 0;
time_t endtime = time(NULL)+lp_ldap_timeout();
-
+
if (!ldap_state)
return (-1);
@@ -1636,7 +1653,7 @@ int smbldap_extended_operation(struct smbldap_state *ldap_state,
}
}
}
-
+
return rc;
}
@@ -1664,7 +1681,7 @@ static void smbldap_idle_fn(struct event_context *event_ctx,
DEBUG(10,("ldap connection not connected...\n"));
return;
}
-
+
if ((state->last_use+SMBLDAP_IDLE_TIME) > now.tv_sec) {
DEBUG(10,("ldap connection not idle...\n"));
@@ -1675,7 +1692,7 @@ static void smbldap_idle_fn(struct event_context *event_ctx,
private_data);
return;
}
-
+
DEBUG(7,("ldap connection idle...closing connection\n"));
smbldap_close(state);
}
@@ -1687,7 +1704,7 @@ static void smbldap_idle_fn(struct event_context *event_ctx,
void smbldap_free_struct(struct smbldap_state **ldap_state)
{
smbldap_close(*ldap_state);
-
+
if ((*ldap_state)->bind_secret) {
memset((*ldap_state)->bind_secret, '\0', strlen((*ldap_state)->bind_secret));
}
diff --git a/source3/lib/util.c b/source3/lib/util.c
index 8e67edeae6..b85f29e136 100644
--- a/source3/lib/util.c
+++ b/source3/lib/util.c
@@ -495,39 +495,6 @@ void set_cmdline_auth_info_getpass(struct user_auth_info *auth_info)
TALLOC_FREE(frame);
}
-/****************************************************************************
- Add a gid to an array of gids if it's not already there.
-****************************************************************************/
-
-bool add_gid_to_array_unique(TALLOC_CTX *mem_ctx, gid_t gid,
- gid_t **gids, size_t *num_gids)
-{
- int i;
-
- if ((*num_gids != 0) && (*gids == NULL)) {
- /*
- * A former call to this routine has failed to allocate memory
- */
- return False;
- }
-
- for (i=0; i<*num_gids; i++) {
- if ((*gids)[i] == gid) {
- return True;
- }
- }
-
- *gids = TALLOC_REALLOC_ARRAY(mem_ctx, *gids, gid_t, *num_gids+1);
- if (*gids == NULL) {
- *num_gids = 0;
- return False;
- }
-
- (*gids)[*num_gids] = gid;
- *num_gids += 1;
- return True;
-}
-
/*******************************************************************
Check if a file exists - call vfs_file_exist for samba files.
********************************************************************/
diff --git a/source3/lib/wb_reqtrans.c b/source3/lib/wb_reqtrans.c
deleted file mode 100644
index 55883ba8c7..0000000000
--- a/source3/lib/wb_reqtrans.c
+++ /dev/null
@@ -1,429 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
-
- Async transfer of winbindd_request and _response structs
-
- Copyright (C) Volker Lendecke 2008
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "includes.h"
-#include "wbc_async.h"
-
-#undef DBGC_CLASS
-#define DBGC_CLASS DBGC_WINBIND
-
-struct req_read_state {
- struct winbindd_request *wb_req;
- size_t max_extra_data;
- ssize_t ret;
-};
-
-static ssize_t wb_req_more(uint8_t *buf, size_t buflen, void *private_data);
-static void wb_req_read_done(struct tevent_req *subreq);
-
-struct tevent_req *wb_req_read_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- int fd, size_t max_extra_data)
-{
- struct tevent_req *req, *subreq;
- struct req_read_state *state;
-
- req = tevent_req_create(mem_ctx, &state, struct req_read_state);
- if (req == NULL) {
- return NULL;
- }
- state->max_extra_data = max_extra_data;
-
- subreq = read_packet_send(state, ev, fd, 4, wb_req_more, state);
- if (tevent_req_nomem(subreq, req)) {
- return tevent_req_post(req, ev);
- }
- tevent_req_set_callback(subreq, wb_req_read_done, req);
- return req;
-}
-
-static ssize_t wb_req_more(uint8_t *buf, size_t buflen, void *private_data)
-{
- struct req_read_state *state = talloc_get_type_abort(
- private_data, struct req_read_state);
- struct winbindd_request *req = (struct winbindd_request *)buf;
-
- if (buflen == 4) {
- if (req->length != sizeof(struct winbindd_request)) {
- DEBUG(0, ("wb_req_read_len: Invalid request size "
- "received: %d (expected %d)\n",
- (int)req->length,
- (int)sizeof(struct winbindd_request)));
- return -1;
- }
- return sizeof(struct winbindd_request) - 4;
- }
-
- if ((state->max_extra_data != 0)
- && (req->extra_len > state->max_extra_data)) {
- DEBUG(3, ("Got request with %d bytes extra data on "
- "unprivileged socket\n", (int)req->extra_len));
- return -1;
- }
-
- return req->extra_len;
-}
-
-static void wb_req_read_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(
- subreq, struct tevent_req);
- struct req_read_state *state = tevent_req_data(
- req, struct req_read_state);
- int err;
- uint8_t *buf;
-
- state->ret = read_packet_recv(subreq, state, &buf, &err);
- TALLOC_FREE(subreq);
- if (state->ret == -1) {
- tevent_req_error(req, err);
- return;
- }
-
- state->wb_req = (struct winbindd_request *)buf;
-
- if (state->wb_req->extra_len != 0) {
- state->wb_req->extra_data.data =
- (char *)buf + sizeof(struct winbindd_request);
- } else {
- state->wb_req->extra_data.data = NULL;
- }
- tevent_req_done(req);
-}
-
-ssize_t wb_req_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
- struct winbindd_request **preq, int *err)
-{
- struct req_read_state *state = tevent_req_data(
- req, struct req_read_state);
-
- if (tevent_req_is_unix_error(req, err)) {
- return -1;
- }
- *preq = talloc_move(mem_ctx, &state->wb_req);
- return state->ret;
-}
-
-struct req_write_state {
- struct iovec iov[2];
- ssize_t ret;
-};
-
-static void wb_req_write_done(struct tevent_req *subreq);
-
-struct tevent_req *wb_req_write_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct tevent_queue *queue, int fd,
- struct winbindd_request *wb_req)
-{
- struct tevent_req *req, *subreq;
- struct req_write_state *state;
- int count = 1;
-
- req = tevent_req_create(mem_ctx, &state, struct req_write_state);
- if (req == NULL) {
- return NULL;
- }
-
- state->iov[0].iov_base = (void *)wb_req;
- state->iov[0].iov_len = sizeof(struct winbindd_request);
-
- if (wb_req->extra_len != 0) {
- state->iov[1].iov_base = (void *)wb_req->extra_data.data;
- state->iov[1].iov_len = wb_req->extra_len;
- count = 2;
- }
-
- subreq = writev_send(state, ev, queue, fd, true, state->iov, count);
- if (tevent_req_nomem(subreq, req)) {
- return tevent_req_post(req, ev);
- }
- tevent_req_set_callback(subreq, wb_req_write_done, req);
- return req;
-}
-
-static void wb_req_write_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(
- subreq, struct tevent_req);
- struct req_write_state *state = tevent_req_data(
- req, struct req_write_state);
- int err;
-
- state->ret = writev_recv(subreq, &err);
- TALLOC_FREE(subreq);
- if (state->ret < 0) {
- tevent_req_error(req, err);
- return;
- }
- tevent_req_done(req);
-}
-
-ssize_t wb_req_write_recv(struct tevent_req *req, int *err)
-{
- struct req_write_state *state = tevent_req_data(
- req, struct req_write_state);
-
- if (tevent_req_is_unix_error(req, err)) {
- return -1;
- }
- return state->ret;
-}
-
-struct resp_read_state {
- struct winbindd_response *wb_resp;
- ssize_t ret;
-};
-
-static ssize_t wb_resp_more(uint8_t *buf, size_t buflen, void *private_data);
-static void wb_resp_read_done(struct tevent_req *subreq);
-
-struct tevent_req *wb_resp_read_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev, int fd)
-{
- struct tevent_req *req, *subreq;
- struct resp_read_state *state;
-
- req = tevent_req_create(mem_ctx, &state, struct resp_read_state);
- if (req == NULL) {
- return NULL;
- }
-
- subreq = read_packet_send(state, ev, fd, 4, wb_resp_more, state);
- if (tevent_req_nomem(subreq, req)) {
- return tevent_req_post(req, ev);
- }
- tevent_req_set_callback(subreq, wb_resp_read_done, req);
- return req;
-}
-
-static ssize_t wb_resp_more(uint8_t *buf, size_t buflen, void *private_data)
-{
- struct winbindd_response *resp = (struct winbindd_response *)buf;
-
- if (buflen == 4) {
- if (resp->length < sizeof(struct winbindd_response)) {
- DEBUG(0, ("wb_resp_read_len: Invalid response size "
- "received: %d (expected at least%d)\n",
- (int)resp->length,
- (int)sizeof(struct winbindd_response)));
- return -1;
- }
- }
- return resp->length - buflen;
-}
-
-static void wb_resp_read_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(
- subreq, struct tevent_req);
- struct resp_read_state *state = tevent_req_data(
- req, struct resp_read_state);
- uint8_t *buf;
- int err;
-
- state->ret = read_packet_recv(subreq, state, &buf, &err);
- TALLOC_FREE(subreq);
- if (state->ret == -1) {
- tevent_req_error(req, err);
- return;
- }
-
- state->wb_resp = (struct winbindd_response *)buf;
-
- if (state->wb_resp->length > sizeof(struct winbindd_response)) {
- state->wb_resp->extra_data.data =
- (char *)buf + sizeof(struct winbindd_response);
- } else {
- state->wb_resp->extra_data.data = NULL;
- }
- tevent_req_done(req);
-}
-
-ssize_t wb_resp_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
- struct winbindd_response **presp, int *err)
-{
- struct resp_read_state *state = tevent_req_data(
- req, struct resp_read_state);
-
- if (tevent_req_is_unix_error(req, err)) {
- return -1;
- }
- *presp = talloc_move(mem_ctx, &state->wb_resp);
- return state->ret;
-}
-
-struct resp_write_state {
- struct iovec iov[2];
- ssize_t ret;
-};
-
-static void wb_resp_write_done(struct tevent_req *subreq);
-
-struct tevent_req *wb_resp_write_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct tevent_queue *queue, int fd,
- struct winbindd_response *wb_resp)
-{
- struct tevent_req *req, *subreq;
- struct resp_write_state *state;
- int count = 1;
-
- req = tevent_req_create(mem_ctx, &state, struct resp_write_state);
- if (req == NULL) {
- return NULL;
- }
-
- state->iov[0].iov_base = (void *)wb_resp;
- state->iov[0].iov_len = sizeof(struct winbindd_response);
-
- if (wb_resp->length > sizeof(struct winbindd_response)) {
- state->iov[1].iov_base = (void *)wb_resp->extra_data.data;
- state->iov[1].iov_len =
- wb_resp->length - sizeof(struct winbindd_response);
- count = 2;
- }
-
- subreq = writev_send(state, ev, queue, fd, true, state->iov, count);
- if (tevent_req_nomem(subreq, req)) {
- return tevent_req_post(req, ev);
- }
- tevent_req_set_callback(subreq, wb_resp_write_done, req);
- return req;
-}
-
-static void wb_resp_write_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(
- subreq, struct tevent_req);
- struct resp_write_state *state = tevent_req_data(
- req, struct resp_write_state);
- int err;
-
- state->ret = writev_recv(subreq, &err);
- TALLOC_FREE(subreq);
- if (state->ret < 0) {
- tevent_req_error(req, err);
- return;
- }
- tevent_req_done(req);
-}
-
-ssize_t wb_resp_write_recv(struct tevent_req *req, int *err)
-{
- struct resp_write_state *state = tevent_req_data(
- req, struct resp_write_state);
-
- if (tevent_req_is_unix_error(req, err)) {
- return -1;
- }
- return state->ret;
-}
-
-struct wb_simple_trans_state {
- struct tevent_context *ev;
- int fd;
- struct winbindd_response *wb_resp;
-};
-
-static void wb_simple_trans_write_done(struct tevent_req *subreq);
-static void wb_simple_trans_read_done(struct tevent_req *subreq);
-
-struct tevent_req *wb_simple_trans_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct tevent_queue *queue, int fd,
- struct winbindd_request *wb_req)
-{
- struct tevent_req *req, *subreq;
- struct wb_simple_trans_state *state;
-
- req = tevent_req_create(mem_ctx, &state, struct wb_simple_trans_state);
- if (req == NULL) {
- return NULL;
- }
-
- wb_req->length = sizeof(struct winbindd_request);
-
- state->ev = ev;
- state->fd = fd;
-
- subreq = wb_req_write_send(state, ev, queue, fd, wb_req);
- if (tevent_req_nomem(subreq, req)) {
- return tevent_req_post(req, ev);
- }
- tevent_req_set_callback(subreq, wb_simple_trans_write_done, req);
-
- return req;
-}
-
-static void wb_simple_trans_write_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(
- subreq, struct tevent_req);
- struct wb_simple_trans_state *state = tevent_req_data(
- req, struct wb_simple_trans_state);
- ssize_t ret;
- int err;
-
- ret = wb_req_write_recv(subreq, &err);
- TALLOC_FREE(subreq);
- if (ret == -1) {
- tevent_req_error(req, err);
- return;
- }
- subreq = wb_resp_read_send(state, state->ev, state->fd);
- if (tevent_req_nomem(subreq, req)) {
- return;
- }
- tevent_req_set_callback(subreq, wb_simple_trans_read_done, req);
-}
-
-static void wb_simple_trans_read_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(
- subreq, struct tevent_req);
- struct wb_simple_trans_state *state = tevent_req_data(
- req, struct wb_simple_trans_state);
- ssize_t ret;
- int err;
-
- ret = wb_resp_read_recv(subreq, state, &state->wb_resp, &err);
- TALLOC_FREE(subreq);
- if (ret == -1) {
- tevent_req_error(req, err);
- return;
- }
-
- tevent_req_done(req);
-}
-
-int wb_simple_trans_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
- struct winbindd_response **presponse, int *err)
-{
- struct wb_simple_trans_state *state = tevent_req_data(
- req, struct wb_simple_trans_state);
-
- if (tevent_req_is_unix_error(req, err)) {
- return -1;
- }
- *presponse = talloc_move(mem_ctx, &state->wb_resp);
- return 0;
-}
diff --git a/source3/lib/wbclient.c b/source3/lib/wbclient.c
deleted file mode 100644
index 164cfc9691..0000000000
--- a/source3/lib/wbclient.c
+++ /dev/null
@@ -1,674 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- Infrastructure for async winbind requests
- Copyright (C) Volker Lendecke 2008
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "includes.h"
-#include "wbc_async.h"
-
-wbcErr map_wbc_err_from_errno(int error)
-{
- switch(error) {
- case EPERM:
- case EACCES:
- return WBC_ERR_AUTH_ERROR;
- case ENOMEM:
- return WBC_ERR_NO_MEMORY;
- case EIO:
- default:
- return WBC_ERR_UNKNOWN_FAILURE;
- }
-}
-
-bool tevent_req_is_wbcerr(struct tevent_req *req, wbcErr *pwbc_err)
-{
- enum tevent_req_state state;
- uint64_t error;
- if (!tevent_req_is_error(req, &state, &error)) {
- *pwbc_err = WBC_ERR_SUCCESS;
- return false;
- }
-
- switch (state) {
- case TEVENT_REQ_USER_ERROR:
- *pwbc_err = error;
- break;
- case TEVENT_REQ_TIMED_OUT:
- *pwbc_err = WBC_ERR_UNKNOWN_FAILURE;
- break;
- case TEVENT_REQ_NO_MEMORY:
- *pwbc_err = WBC_ERR_NO_MEMORY;
- break;
- default:
- *pwbc_err = WBC_ERR_UNKNOWN_FAILURE;
- break;
- }
- return true;
-}
-
-wbcErr tevent_req_simple_recv_wbcerr(struct tevent_req *req)
-{
- wbcErr wbc_err;
-
- if (tevent_req_is_wbcerr(req, &wbc_err)) {
- return wbc_err;
- }
-
- return WBC_ERR_SUCCESS;
-}
-
-struct wb_context {
- struct tevent_queue *queue;
- int fd;
- bool is_priv;
-};
-
-static int make_nonstd_fd(int fd)
-{
- int i;
- int sys_errno = 0;
- int fds[3];
- int num_fds = 0;
-
- if (fd == -1) {
- return -1;
- }
- while (fd < 3) {
- fds[num_fds++] = fd;
- fd = dup(fd);
- if (fd == -1) {
- sys_errno = errno;
- break;
- }
- }
- for (i=0; i<num_fds; i++) {
- close(fds[i]);
- }
- if (fd == -1) {
- errno = sys_errno;
- }
- return fd;
-}
-
-/****************************************************************************
- Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
- else
- if SYSV use O_NDELAY
- if BSD use FNDELAY
- Set close on exec also.
-****************************************************************************/
-
-static int make_safe_fd(int fd)
-{
- int result, flags;
- int new_fd = make_nonstd_fd(fd);
-
- if (new_fd == -1) {
- goto fail;
- }
-
- /* Socket should be nonblocking. */
-
-#ifdef O_NONBLOCK
-#define FLAG_TO_SET O_NONBLOCK
-#else
-#ifdef SYSV
-#define FLAG_TO_SET O_NDELAY
-#else /* BSD */
-#define FLAG_TO_SET FNDELAY
-#endif
-#endif
-
- if ((flags = fcntl(new_fd, F_GETFL)) == -1) {
- goto fail;
- }
-
- flags |= FLAG_TO_SET;
- if (fcntl(new_fd, F_SETFL, flags) == -1) {
- goto fail;
- }
-
-#undef FLAG_TO_SET
-
- /* Socket should be closed on exec() */
-#ifdef FD_CLOEXEC
- result = flags = fcntl(new_fd, F_GETFD, 0);
- if (flags >= 0) {
- flags |= FD_CLOEXEC;
- result = fcntl( new_fd, F_SETFD, flags );
- }
- if (result < 0) {
- goto fail;
- }
-#endif
- return new_fd;
-
- fail:
- if (new_fd != -1) {
- int sys_errno = errno;
- close(new_fd);
- errno = sys_errno;
- }
- return -1;
-}
-
-struct wb_context *wb_context_init(TALLOC_CTX *mem_ctx)
-{
- struct wb_context *result;
-
- result = talloc(mem_ctx, struct wb_context);
- if (result == NULL) {
- return NULL;
- }
- result->queue = tevent_queue_create(result, "wb_trans");
- if (result->queue == NULL) {
- TALLOC_FREE(result);
- return NULL;
- }
- result->fd = -1;
- result->is_priv = false;
- return result;
-}
-
-struct wb_connect_state {
- int dummy;
-};
-
-static void wbc_connect_connected(struct tevent_req *subreq);
-
-static struct tevent_req *wb_connect_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct wb_context *wb_ctx,
- const char *dir)
-{
- struct tevent_req *result, *subreq;
- struct wb_connect_state *state;
- struct sockaddr_un sunaddr;
- struct stat st;
- char *path = NULL;
- wbcErr wbc_err;
-
- result = tevent_req_create(mem_ctx, &state, struct wb_connect_state);
- if (result == NULL) {
- return NULL;
- }
-
- if (wb_ctx->fd != -1) {
- close(wb_ctx->fd);
- wb_ctx->fd = -1;
- }
-
- /* Check permissions on unix socket directory */
-
- if (lstat(dir, &st) == -1) {
- wbc_err = WBC_ERR_WINBIND_NOT_AVAILABLE;
- goto post_status;
- }
-
- if (!S_ISDIR(st.st_mode) ||
- (st.st_uid != 0 && st.st_uid != geteuid())) {
- wbc_err = WBC_ERR_WINBIND_NOT_AVAILABLE;
- goto post_status;
- }
-
- /* Connect to socket */
-
- path = talloc_asprintf(talloc_tos(), "%s/%s", dir,
- WINBINDD_SOCKET_NAME);
- if (path == NULL) {
- goto nomem;
- }
-
- sunaddr.sun_family = AF_UNIX;
- strlcpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path));
- TALLOC_FREE(path);
-
- /* If socket file doesn't exist, don't bother trying to connect
- with retry. This is an attempt to make the system usable when
- the winbindd daemon is not running. */
-
- if ((lstat(sunaddr.sun_path, &st) == -1)
- || !S_ISSOCK(st.st_mode)
- || (st.st_uid != 0 && st.st_uid != geteuid())) {
- wbc_err = WBC_ERR_WINBIND_NOT_AVAILABLE;
- goto post_status;
- }
-
- wb_ctx->fd = make_safe_fd(socket(AF_UNIX, SOCK_STREAM, 0));
- if (wb_ctx->fd == -1) {
- wbc_err = map_wbc_err_from_errno(errno);
- goto post_status;
- }
-
- subreq = async_connect_send(mem_ctx, ev, wb_ctx->fd,
- (struct sockaddr *)(void *)&sunaddr,
- sizeof(sunaddr));
- if (subreq == NULL) {
- goto nomem;
- }
- tevent_req_set_callback(subreq, wbc_connect_connected, result);
- return result;
-
- post_status:
- tevent_req_error(result, wbc_err);
- return tevent_req_post(result, ev);
- nomem:
- TALLOC_FREE(result);
- return NULL;
-}
-
-static void wbc_connect_connected(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(
- subreq, struct tevent_req);
- int res, err;
-
- res = async_connect_recv(subreq, &err);
- TALLOC_FREE(subreq);
- if (res == -1) {
- tevent_req_error(req, map_wbc_err_from_errno(err));
- return;
- }
- tevent_req_done(req);
-}
-
-static wbcErr wb_connect_recv(struct tevent_req *req)
-{
- return tevent_req_simple_recv_wbcerr(req);
-}
-
-static const char *winbindd_socket_dir(void)
-{
-#ifdef SOCKET_WRAPPER
- const char *env_dir;
-
- env_dir = getenv(WINBINDD_SOCKET_DIR_ENVVAR);
- if (env_dir) {
- return env_dir;
- }
-#endif
-
- return WINBINDD_SOCKET_DIR;
-}
-
-struct wb_open_pipe_state {
- struct wb_context *wb_ctx;
- struct tevent_context *ev;
- bool need_priv;
- struct winbindd_request wb_req;
-};
-
-static void wb_open_pipe_connect_nonpriv_done(struct tevent_req *subreq);
-static void wb_open_pipe_ping_done(struct tevent_req *subreq);
-static void wb_open_pipe_getpriv_done(struct tevent_req *subreq);
-static void wb_open_pipe_connect_priv_done(struct tevent_req *subreq);
-
-static struct tevent_req *wb_open_pipe_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct wb_context *wb_ctx,
- bool need_priv)
-{
- struct tevent_req *result, *subreq;
- struct wb_open_pipe_state *state;
-
- result = tevent_req_create(mem_ctx, &state, struct wb_open_pipe_state);
- if (result == NULL) {
- return NULL;
- }
- state->wb_ctx = wb_ctx;
- state->ev = ev;
- state->need_priv = need_priv;
-
- if (wb_ctx->fd != -1) {
- close(wb_ctx->fd);
- wb_ctx->fd = -1;
- }
-
- subreq = wb_connect_send(state, ev, wb_ctx, winbindd_socket_dir());
- if (subreq == NULL) {
- goto fail;
- }
- tevent_req_set_callback(subreq, wb_open_pipe_connect_nonpriv_done,
- result);
- return result;
-
- fail:
- TALLOC_FREE(result);
- return NULL;
-}
-
-static void wb_open_pipe_connect_nonpriv_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(
- subreq, struct tevent_req);
- struct wb_open_pipe_state *state = tevent_req_data(
- req, struct wb_open_pipe_state);
- wbcErr wbc_err;
-
- wbc_err = wb_connect_recv(subreq);
- TALLOC_FREE(subreq);
- if (!WBC_ERROR_IS_OK(wbc_err)) {
- state->wb_ctx->is_priv = true;
- tevent_req_error(req, wbc_err);
- return;
- }
-
- ZERO_STRUCT(state->wb_req);
- state->wb_req.cmd = WINBINDD_INTERFACE_VERSION;
- state->wb_req.pid = getpid();
-
- subreq = wb_simple_trans_send(state, state->ev, NULL,
- state->wb_ctx->fd, &state->wb_req);
- if (tevent_req_nomem(subreq, req)) {
- return;
- }
- tevent_req_set_callback(subreq, wb_open_pipe_ping_done, req);
-}
-
-static void wb_open_pipe_ping_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(
- subreq, struct tevent_req);
- struct wb_open_pipe_state *state = tevent_req_data(
- req, struct wb_open_pipe_state);
- struct winbindd_response *wb_resp;
- int ret, err;
-
- ret = wb_simple_trans_recv(subreq, state, &wb_resp, &err);
- TALLOC_FREE(subreq);
- if (ret == -1) {
- tevent_req_error(req, map_wbc_err_from_errno(err));
- return;
- }
-
- if (!state->need_priv) {
- tevent_req_done(req);
- return;
- }
-
- state->wb_req.cmd = WINBINDD_PRIV_PIPE_DIR;
- state->wb_req.pid = getpid();
-
- subreq = wb_simple_trans_send(state, state->ev, NULL,
- state->wb_ctx->fd, &state->wb_req);
- if (tevent_req_nomem(subreq, req)) {
- return;
- }
- tevent_req_set_callback(subreq, wb_open_pipe_getpriv_done, req);
-}
-
-static void wb_open_pipe_getpriv_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(
- subreq, struct tevent_req);
- struct wb_open_pipe_state *state = tevent_req_data(
- req, struct wb_open_pipe_state);
- struct winbindd_response *wb_resp = NULL;
- int ret, err;
-
- ret = wb_simple_trans_recv(subreq, state, &wb_resp, &err);
- TALLOC_FREE(subreq);
- if (ret == -1) {
- tevent_req_error(req, map_wbc_err_from_errno(err));
- return;
- }
-
- close(state->wb_ctx->fd);
- state->wb_ctx->fd = -1;
-
- subreq = wb_connect_send(state, state->ev, state->wb_ctx,
- (char *)wb_resp->extra_data.data);
- TALLOC_FREE(wb_resp);
- if (tevent_req_nomem(subreq, req)) {
- return;
- }
- tevent_req_set_callback(subreq, wb_open_pipe_connect_priv_done, req);
-}
-
-static void wb_open_pipe_connect_priv_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(
- subreq, struct tevent_req);
- struct wb_open_pipe_state *state = tevent_req_data(
- req, struct wb_open_pipe_state);
- wbcErr wbc_err;
-
- wbc_err = wb_connect_recv(subreq);
- TALLOC_FREE(subreq);
- if (!WBC_ERROR_IS_OK(wbc_err)) {
- tevent_req_error(req, wbc_err);
- return;
- }
- state->wb_ctx->is_priv = true;
- tevent_req_done(req);
-}
-
-static wbcErr wb_open_pipe_recv(struct tevent_req *req)
-{
- return tevent_req_simple_recv_wbcerr(req);
-}
-
-struct wb_trans_state {
- struct wb_trans_state *prev, *next;
- struct wb_context *wb_ctx;
- struct tevent_context *ev;
- struct winbindd_request *wb_req;
- struct winbindd_response *wb_resp;
- bool need_priv;
-};
-
-static bool closed_fd(int fd)
-{
- struct timeval tv;
- fd_set r_fds;
- int selret;
-
- if (fd == -1) {
- return true;
- }
-
- FD_ZERO(&r_fds);
- FD_SET(fd, &r_fds);
- ZERO_STRUCT(tv);
-
- selret = select(fd+1, &r_fds, NULL, NULL, &tv);
- if (selret == -1) {
- return true;
- }
- if (selret == 0) {
- return false;
- }
- return (FD_ISSET(fd, &r_fds));
-}
-
-static void wb_trans_trigger(struct tevent_req *req, void *private_data);
-static void wb_trans_connect_done(struct tevent_req *subreq);
-static void wb_trans_done(struct tevent_req *subreq);
-static void wb_trans_retry_wait_done(struct tevent_req *subreq);
-
-struct tevent_req *wb_trans_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct wb_context *wb_ctx, bool need_priv,
- struct winbindd_request *wb_req)
-{
- struct tevent_req *req;
- struct wb_trans_state *state;
-
- req = tevent_req_create(mem_ctx, &state, struct wb_trans_state);
- if (req == NULL) {
- return NULL;
- }
- state->wb_ctx = wb_ctx;
- state->ev = ev;
- state->wb_req = wb_req;
- state->need_priv = need_priv;
-
- if (!tevent_queue_add(wb_ctx->queue, ev, req, wb_trans_trigger,
- NULL)) {
- tevent_req_nomem(NULL, req);
- return tevent_req_post(req, ev);
- }
- return req;
-}
-
-static void wb_trans_trigger(struct tevent_req *req, void *private_data)
-{
- struct wb_trans_state *state = tevent_req_data(
- req, struct wb_trans_state);
- struct tevent_req *subreq;
-
- if ((state->wb_ctx->fd != -1) && closed_fd(state->wb_ctx->fd)) {
- close(state->wb_ctx->fd);
- state->wb_ctx->fd = -1;
- }
-
- if ((state->wb_ctx->fd == -1)
- || (state->need_priv && !state->wb_ctx->is_priv)) {
- subreq = wb_open_pipe_send(state, state->ev, state->wb_ctx,
- state->need_priv);
- if (tevent_req_nomem(subreq, req)) {
- return;
- }
- tevent_req_set_callback(subreq, wb_trans_connect_done, req);
- return;
- }
-
- state->wb_req->pid = getpid();
-
- subreq = wb_simple_trans_send(state, state->ev, NULL,
- state->wb_ctx->fd, state->wb_req);
- if (tevent_req_nomem(subreq, req)) {
- return;
- }
- tevent_req_set_callback(subreq, wb_trans_done, req);
-}
-
-static bool wb_trans_retry(struct tevent_req *req,
- struct wb_trans_state *state,
- wbcErr wbc_err)
-{
- struct tevent_req *subreq;
-
- if (WBC_ERROR_IS_OK(wbc_err)) {
- return false;
- }
-
- if (wbc_err == WBC_ERR_WINBIND_NOT_AVAILABLE) {
- /*
- * Winbind not around or we can't connect to the pipe. Fail
- * immediately.
- */
- tevent_req_error(req, wbc_err);
- return true;
- }
-
- /*
- * The transfer as such failed, retry after one second
- */
-
- if (state->wb_ctx->fd != -1) {
- close(state->wb_ctx->fd);
- state->wb_ctx->fd = -1;
- }
-
- subreq = tevent_wakeup_send(state, state->ev,
- timeval_current_ofs(1, 0));
- if (tevent_req_nomem(subreq, req)) {
- return true;
- }
- tevent_req_set_callback(subreq, wb_trans_retry_wait_done, req);
- return true;
-}
-
-static void wb_trans_retry_wait_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(
- subreq, struct tevent_req);
- struct wb_trans_state *state = tevent_req_data(
- req, struct wb_trans_state);
- bool ret;
-
- ret = tevent_wakeup_recv(subreq);
- TALLOC_FREE(subreq);
- if (!ret) {
- tevent_req_error(req, WBC_ERR_UNKNOWN_FAILURE);
- return;
- }
-
- subreq = wb_open_pipe_send(state, state->ev, state->wb_ctx,
- state->need_priv);
- if (tevent_req_nomem(subreq, req)) {
- return;
- }
- tevent_req_set_callback(subreq, wb_trans_connect_done, req);
-}
-
-static void wb_trans_connect_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(
- subreq, struct tevent_req);
- struct wb_trans_state *state = tevent_req_data(
- req, struct wb_trans_state);
- wbcErr wbc_err;
-
- wbc_err = wb_open_pipe_recv(subreq);
- TALLOC_FREE(subreq);
-
- if (wb_trans_retry(req, state, wbc_err)) {
- return;
- }
-
- subreq = wb_simple_trans_send(state, state->ev, NULL,
- state->wb_ctx->fd, state->wb_req);
- if (tevent_req_nomem(subreq, req)) {
- return;
- }
- tevent_req_set_callback(subreq, wb_trans_done, req);
-}
-
-static void wb_trans_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(
- subreq, struct tevent_req);
- struct wb_trans_state *state = tevent_req_data(
- req, struct wb_trans_state);
- int ret, err;
-
- ret = wb_simple_trans_recv(subreq, state, &state->wb_resp, &err);
- TALLOC_FREE(subreq);
- if ((ret == -1)
- && wb_trans_retry(req, state, map_wbc_err_from_errno(err))) {
- return;
- }
-
- tevent_req_done(req);
-}
-
-wbcErr wb_trans_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
- struct winbindd_response **presponse)
-{
- struct wb_trans_state *state = tevent_req_data(
- req, struct wb_trans_state);
- wbcErr wbc_err;
-
- if (tevent_req_is_wbcerr(req, &wbc_err)) {
- return wbc_err;
- }
-
- *presponse = talloc_move(mem_ctx, &state->wb_resp);
- return WBC_ERR_SUCCESS;
-}