summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
Diffstat (limited to 'source3')
-rw-r--r--source3/nsswitch/pam_winbind.h85
-rw-r--r--source3/nsswitch/winbindd_glue.c364
-rw-r--r--source3/nsswitch/winbindd_misc.c159
-rw-r--r--source3/nsswitch/winbindd_sid.c244
4 files changed, 852 insertions, 0 deletions
diff --git a/source3/nsswitch/pam_winbind.h b/source3/nsswitch/pam_winbind.h
new file mode 100644
index 0000000000..85707cb4dc
--- /dev/null
+++ b/source3/nsswitch/pam_winbind.h
@@ -0,0 +1,85 @@
+/* pam_winbind header file
+ (Solaris needs some macros from Linux for common PAM code)
+
+ Shirish Kalele 2000
+*/
+
+#ifdef HAVE_FEATURES_H
+#include <features.h>
+#endif
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <syslog.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <config.h>
+
+#define MODULE_NAME "pam_winbind"
+#define PAM_SM_AUTH
+#define PAM_SM_ACCOUNT
+#define PAM_SM_PASSWORD
+
+#if defined(SUNOS5) || defined(SUNOS4)
+
+/* Solaris always uses dynamic pam modules */
+#define PAM_EXTERN extern
+#include <security/pam_appl.h>
+
+#define PAM_AUTHTOK_RECOVER_ERR PAM_AUTHTOK_RECOVERY_ERR
+#endif
+
+#include <security/pam_modules.h>
+
+#ifdef HAVE_SECURITY__PAM_MACROS_H
+#include <security/_pam_macros.h>
+#else
+/* Define required macros from (Linux PAM 0.68) security/_pam_macros.h */
+#define _pam_drop_reply(/* struct pam_response * */ reply, /* int */ replies) \
+do { \
+ int reply_i; \
+ \
+ for (reply_i=0; reply_i<replies; ++reply_i) { \
+ if (reply[reply_i].resp) { \
+ _pam_overwrite(reply[reply_i].resp); \
+ free(reply[reply_i].resp); \
+ } \
+ } \
+ if (reply) \
+ free(reply); \
+} while (0)
+
+#define _pam_overwrite(x) \
+do { \
+ register char *__xx__; \
+ if ((__xx__=(x))) \
+ while (*__xx__) \
+ *__xx__++ = '\0'; \
+} while (0)
+
+/*
+ * Don't just free it, forget it too.
+ */
+
+#define _pam_drop(X) \
+do { \
+ if (X) { \
+ free(X); \
+ X=NULL; \
+ } \
+} while (0)
+
+#define x_strdup(s) ( (s) ? strdup(s):NULL )
+#endif
+
+#define PAM_DEBUG_ARG (1<<0)
+#define PAM_USE_AUTHTOK_ARG (1<<1)
+#define PAM_UNKNOWN_OK_ARG (1<<2)
+
+#include "winbind_nss_config.h"
+#include "winbindd_nss.h"
diff --git a/source3/nsswitch/winbindd_glue.c b/source3/nsswitch/winbindd_glue.c
new file mode 100644
index 0000000000..ac8c60d26c
--- /dev/null
+++ b/source3/nsswitch/winbindd_glue.c
@@ -0,0 +1,364 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 2.0
+
+ Winbind daemon glue functions to connect new cli interface
+ to older style lsa_ and samr_ functions
+
+ Copyright (C) tridge@samba.org 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 2 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, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "winbindd.h"
+
+/****************************************************************************
+do a LSA Open Policy
+****************************************************************************/
+BOOL lsa_open_policy(char *server, BOOL sec_qos, uint32 des_access,
+ CLI_POLICY_HND *pol)
+{
+ struct nmb_name calling, called;
+ struct ntuser_creds creds;
+ struct in_addr dest_ip;
+ fstring dest_host;
+ uint32 result = NT_STATUS_UNSUCCESSFUL;
+ extern pstring global_myname;
+
+ ZERO_STRUCTP(pol);
+
+ pol->cli = (struct cli_state *)malloc(sizeof(struct cli_state));
+ pol->mem_ctx = talloc_init();
+
+ if (!pol->cli || !pol->mem_ctx)
+ return False;
+
+ /* Initialise RPC connection */
+
+ ZERO_STRUCT(creds);
+ creds.pwd.null_pwd = 1;
+
+ cli_init_creds(pol->cli, &creds);
+
+ /* Establish a SMB connection */
+
+ if (!resolve_srv_name(server, dest_host, &dest_ip)) {
+ goto done;
+ }
+
+ make_nmb_name(&called, dns_to_netbios_name(dest_host), 0x20);
+ make_nmb_name(&calling, dns_to_netbios_name(global_myname), 0);
+
+ if (!cli_establish_connection(pol->cli, dest_host, &dest_ip, &calling,
+ &called, "IPC$", "IPC", False, True)) {
+ goto done;
+ }
+
+ if (!cli_nt_session_open (pol->cli, PIPE_LSARPC)) {
+ goto done;
+ }
+
+ result = cli_lsa_open_policy(pol->cli, pol->mem_ctx, sec_qos,
+ des_access, &pol->handle);
+
+ done:
+ if (result != NT_STATUS_NOPROBLEMO && pol->cli) {
+ if (pol->cli->initialised)
+ cli_shutdown(pol->cli);
+ free(pol->cli);
+ }
+
+ return (result == NT_STATUS_NOPROBLEMO);
+}
+
+/****************************************************************************
+do a LSA Enumerate Trusted Domain
+****************************************************************************/
+BOOL lsa_enum_trust_dom(CLI_POLICY_HND *hnd, uint32 *enum_ctx,
+ uint32 * num_doms, char ***names, DOM_SID **sids)
+{
+ uint32 ret;
+
+ ret = cli_lsa_enum_trust_dom(hnd->cli, hnd->mem_ctx, &hnd->handle,
+ enum_ctx, num_doms, names, sids);
+
+ return (ret == NT_STATUS_NOPROBLEMO);
+}
+
+/****************************************************************************
+do a LSA Query Info Policy
+****************************************************************************/
+BOOL lsa_query_info_pol(CLI_POLICY_HND *hnd, uint16 info_class,
+ fstring domain_name, DOM_SID *domain_sid)
+{
+ uint32 ret;
+
+ ret = cli_lsa_query_info_policy(hnd->cli, hnd->mem_ctx, &hnd->handle,
+ info_class, domain_name, domain_sid);
+
+ return (ret == NT_STATUS_NOPROBLEMO);
+}
+
+/****************************************************************************
+do a LSA Lookup Names
+****************************************************************************/
+BOOL lsa_lookup_names(CLI_POLICY_HND *hnd, int num_names, char **names,
+ DOM_SID **sids, uint32 **types, int *num_sids)
+{
+ uint32 ret;
+
+ ret = cli_lsa_lookup_names(hnd->cli, hnd->mem_ctx, &hnd->handle,
+ num_names, names, sids, types, num_sids);
+
+ return (ret == NT_STATUS_NOPROBLEMO);
+}
+
+/****************************************************************************
+do a LSA Lookup SIDS
+****************************************************************************/
+BOOL lsa_lookup_sids(CLI_POLICY_HND *hnd, int num_sids, DOM_SID *sids,
+ char ***names, uint32 **types, int *num_names)
+{
+ uint32 ret;
+
+ ret = cli_lsa_lookup_sids(hnd->cli, hnd->mem_ctx, &hnd->handle,
+ num_sids, sids, names, types, num_names);
+
+ return (ret == NT_STATUS_NOPROBLEMO);
+}
+
+/****************************************************************************
+lsa_close glue
+****************************************************************************/
+BOOL lsa_close(CLI_POLICY_HND *hnd)
+{
+ uint32 ret;
+
+ ret = cli_lsa_close(hnd->cli, hnd->mem_ctx, &hnd->handle);
+
+ return (ret == NT_STATUS_NOPROBLEMO);
+}
+
+
+/****************************************************************************
+samr_close glue
+****************************************************************************/
+BOOL samr_close(CLI_POLICY_HND *hnd)
+{
+ uint32 ret;
+
+ ret = cli_samr_close(hnd->cli, hnd->mem_ctx, &hnd->handle);
+
+ return (ret == NT_STATUS_NOPROBLEMO);
+}
+
+
+/****************************************************************************
+samr_connect glue
+****************************************************************************/
+BOOL samr_connect(char *srv_name, uint32 access_mask,
+ CLI_POLICY_HND *connect_pol)
+{
+ uint32 ret;
+
+ ret = cli_samr_connect(connect_pol->cli, connect_pol->mem_ctx,
+ srv_name, access_mask,
+ &connect_pol->handle);
+
+ return (ret == NT_STATUS_NOPROBLEMO);
+}
+
+
+/****************************************************************************
+samr_open_domain glue
+****************************************************************************/
+BOOL samr_open_domain(CLI_POLICY_HND *connect_pol,
+ uint32 ace_perms,
+ DOM_SID *sid,
+ CLI_POLICY_HND *domain_pol)
+{
+ uint32 ret;
+
+ ret = cli_samr_open_domain(connect_pol->cli,
+ connect_pol->mem_ctx,
+ &connect_pol->handle,
+ ace_perms,
+ sid,
+ &domain_pol->handle);
+
+ if (ret == NT_STATUS_NOPROBLEMO) {
+ domain_pol->cli = connect_pol->cli;
+ return True;
+ }
+
+ return False;
+}
+
+/*******************************************************************
+frees a structure.
+********************************************************************/
+void free_samr_userinfo_ctr(SAM_USERINFO_CTR * ctr)
+{
+ if (ctr == NULL)
+ return;
+ safe_free(ctr->info.id);
+ ctr->info.id = NULL;
+}
+
+/****************************************************************************
+do a SAMR enumerate groups
+****************************************************************************/
+uint32 samr_enum_dom_groups(CLI_POLICY_HND *pol,
+ uint32 *start_idx, uint32 size,
+ struct acct_info **sam,
+ uint32 *num_sam_groups)
+{
+ DEBUG(0,("unimplemented samr_enum_dom_groups\n"));
+ return -1;
+}
+
+/****************************************************************************
+do a SAMR enumerate groups
+****************************************************************************/
+BOOL get_samr_query_userinfo(CLI_POLICY_HND *pol, uint32 info_level,
+ uint32 user_rid, SAM_USERINFO_CTR *ctr)
+{
+ POLICY_HND user_pol;
+ BOOL got_user_pol = False;
+ uint32 result;
+
+ if ((result = cli_samr_open_user(pol->cli, pol->mem_ctx,
+ &pol->handle, MAXIMUM_ALLOWED_ACCESS,
+ user_rid, &user_pol))
+ != NT_STATUS_NOPROBLEMO)
+ goto done;
+
+ got_user_pol = True;
+
+ if ((result = cli_samr_query_userinfo(pol->cli, pol->mem_ctx,
+ &user_pol, info_level, ctr))
+ != NT_STATUS_NOPROBLEMO)
+ goto done;
+
+ done:
+ if (got_user_pol) cli_samr_close(pol->cli, pol->mem_ctx, &user_pol);
+
+ return (result != NT_STATUS_NOPROBLEMO);
+}
+
+/****************************************************************************
+do a SAMR enumerate groups
+****************************************************************************/
+BOOL samr_open_user(CLI_POLICY_HND *pol, uint32 access_mask, uint32 rid,
+ POLICY_HND *user_pol)
+{
+ uint32 ret;
+
+ ret = cli_samr_open_user(pol->cli, pol->mem_ctx, &pol->handle,
+ access_mask, rid, user_pol);
+
+ return (ret == NT_STATUS_NOPROBLEMO);
+}
+
+BOOL samr_query_usergroups(CLI_POLICY_HND *pol, uint32 *num_groups,
+ DOM_GID **gid)
+{
+ uint32 ret;
+
+ ret = cli_samr_query_usergroups(pol->cli, pol->mem_ctx, &pol->handle,
+ num_groups, gid);
+
+ return (ret == NT_STATUS_NOPROBLEMO);
+}
+
+BOOL get_samr_query_groupinfo(CLI_POLICY_HND *pol, uint32 info_level,
+ uint32 group_rid, GROUP_INFO_CTR *ctr)
+{
+ POLICY_HND group_pol;
+ BOOL got_group_pol = False;
+ uint32 result;
+
+ if ((result = cli_samr_open_group(pol->cli, pol->mem_ctx,
+ &pol->handle, MAXIMUM_ALLOWED_ACCESS,
+ group_rid, &group_pol))
+ != NT_STATUS_NOPROBLEMO)
+ goto done;
+
+ got_group_pol = True;
+
+ if ((result = cli_samr_query_groupinfo(pol->cli, pol->mem_ctx,
+ &group_pol, info_level,
+ ctr)) != NT_STATUS_NOPROBLEMO)
+ goto done;
+
+ done:
+ if (got_group_pol) cli_samr_close(pol->cli, pol->mem_ctx, &group_pol);
+
+ return (result == NT_STATUS_NOPROBLEMO);
+}
+
+BOOL sam_query_groupmem(CLI_POLICY_HND *pol, uint32 group_rid,
+ uint32 *num_names, uint32 **rid_mem, char ***names,
+ uint32 **name_types)
+{
+ BOOL got_group_pol = False;
+ POLICY_HND group_pol;
+ uint32 result;
+
+ if ((result = cli_samr_open_group(pol->cli, pol->mem_ctx,
+ &pol->handle, MAXIMUM_ALLOWED_ACCESS,
+ group_rid, &group_pol))
+ != NT_STATUS_NOPROBLEMO)
+ goto done;
+
+ got_group_pol = True;
+
+ if ((result = cli_samr_query_groupmem(pol->cli, pol->mem_ctx,
+ &group_pol, num_names, rid_mem,
+ name_types))
+ != NT_STATUS_NOPROBLEMO)
+ goto done;
+
+ /* do a samr_query_lookup_rids() */
+
+ done:
+ if (got_group_pol) cli_samr_close(pol->cli, pol->mem_ctx, &group_pol);
+
+ return (result == NT_STATUS_NOPROBLEMO);
+}
+
+BOOL samr_query_dom_info(CLI_POLICY_HND *pol, uint16 switch_value,
+ SAM_UNK_CTR *ctr)
+{
+ uint32 ret;
+
+ ret = cli_samr_query_dom_info(pol->cli, pol->mem_ctx,
+ &pol->handle, switch_value, ctr);
+
+ return (ret == NT_STATUS_NOPROBLEMO);
+}
+
+BOOL samr_query_dispinfo(CLI_POLICY_HND *pol, uint32 *start_ndx,
+ uint16 info_level, uint32 *num_entries,
+ SAM_DISPINFO_CTR *ctr)
+{
+ uint32 ret;
+
+ ret = cli_samr_query_dispinfo(pol->cli, pol->mem_ctx,
+ &pol->handle, start_ndx, info_level,
+ num_entries, 0xffff, ctr);
+
+ return (ret == NT_STATUS_NOPROBLEMO);
+}
diff --git a/source3/nsswitch/winbindd_misc.c b/source3/nsswitch/winbindd_misc.c
new file mode 100644
index 0000000000..182f983efb
--- /dev/null
+++ b/source3/nsswitch/winbindd_misc.c
@@ -0,0 +1,159 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 2.0
+
+ Winbind daemon - miscellaneous other functions
+
+ Copyright (C) Tim Potter 2000
+
+ 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 2 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, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "winbindd.h"
+
+extern pstring global_myname;
+
+/* Some routines to fetch the trust account password from a HEAD
+ version of Samba. Yuck. )-: */
+
+/************************************************************************
+form a key for fetching a domain trust password from
+************************************************************************/
+static char *trust_keystr(char *domain)
+{
+ static fstring keystr;
+
+ snprintf(keystr,sizeof(keystr),"%s/%s", SECRETS_MACHINE_ACCT_PASS,
+ domain);
+
+ return keystr;
+}
+
+/************************************************************************
+ Routine to get the trust account password for a domain
+************************************************************************/
+BOOL _get_trust_account_password(char *domain, unsigned char *ret_pwd,
+ time_t *pass_last_set_time)
+{
+ struct machine_acct_pass *pass;
+ fstring dos_domain;
+ size_t size;
+
+ fstrcpy(dos_domain, domain);
+ unix_to_dos(dos_domain, True);
+
+ if (!(pass = secrets_fetch(trust_keystr(dos_domain), &size)) ||
+ size != sizeof(*pass)) return False;
+
+ if (pass_last_set_time) *pass_last_set_time = pass->mod_time;
+ memcpy(ret_pwd, pass->hash, 16);
+ free(pass);
+ return True;
+}
+
+/* Check the machine account password is valid */
+
+enum winbindd_result winbindd_check_machine_acct(
+ struct winbindd_cli_state *state)
+{
+ int result = WINBINDD_ERROR;
+ uchar trust_passwd[16];
+ struct in_addr *ip_list = NULL;
+ int count;
+ uint16 validation_level;
+ fstring controller, trust_account;
+
+ DEBUG(3, ("[%5d]: check machine account\n", state->pid));
+
+ /* Get trust account password */
+
+ if (!_get_trust_account_password(lp_workgroup(), trust_passwd, NULL)) {
+ result = NT_STATUS_INTERNAL_ERROR;
+ goto done;
+ }
+
+ /* Get domain controller */
+
+ if (!get_dc_list(True, lp_workgroup(), &ip_list, &count) ||
+ !lookup_pdc_name(global_myname, lp_workgroup(), &ip_list[0],
+ controller)) {
+ DEBUG(0, ("could not find domain controller for "
+ "domain %s\n", lp_workgroup()));
+ result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
+ goto done;
+ }
+
+ DEBUG(3, ("contacting controller %s to check secret\n", controller));
+
+ /* Contact domain controller to check secret */
+
+ slprintf(trust_account, sizeof(trust_account) - 1, "%s$",
+ global_myname);
+
+#if 0 /* XXX */
+ result = cli_nt_setup_creds(controller, lp_workgroup(), global_myname,
+ trust_account, trust_passwd,
+ SEC_CHAN_WKSTA, &validation_level);
+#endif
+
+ /* Pass back result code - zero for success, other values for
+ specific failures. */
+
+ DEBUG(3, ("secret is %s\n", (result == NT_STATUS_NOPROBLEMO) ?
+ "good" : "bad"));
+
+ done:
+ state->response.data.num_entries = result;
+ return WINBINDD_OK;
+}
+
+enum winbindd_result winbindd_list_trusted_domains(struct winbindd_cli_state
+ *state)
+{
+ struct winbindd_domain *domain;
+ int total_entries = 0, extra_data_len = 0;
+ char *extra_data = NULL;
+
+ DEBUG(3, ("[%5d]: list trusted domains\n", state->pid));
+
+ for(domain = domain_list; domain; domain = domain->next) {
+
+ /* Skip own domain */
+
+ if (strequal(domain->name, lp_workgroup())) continue;
+
+ /* Add domain to list */
+
+ total_entries++;
+ extra_data = Realloc(extra_data, sizeof(fstring) *
+ total_entries);
+
+ if (!extra_data) return WINBINDD_ERROR;
+
+ memcpy(&extra_data[extra_data_len], domain->name,
+ strlen(domain->name));
+
+ extra_data_len += strlen(domain->name);
+ extra_data[extra_data_len++] = ',';
+ }
+
+ if (extra_data) {
+ if (extra_data_len > 1) extra_data[extra_data_len - 1] = '\0';
+ state->response.extra_data = extra_data;
+ state->response.length += extra_data_len;
+ }
+
+ return WINBINDD_OK;
+}
diff --git a/source3/nsswitch/winbindd_sid.c b/source3/nsswitch/winbindd_sid.c
new file mode 100644
index 0000000000..bc014f2691
--- /dev/null
+++ b/source3/nsswitch/winbindd_sid.c
@@ -0,0 +1,244 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 2.0
+
+ Winbind daemon - sid related functions
+
+ Copyright (C) Tim Potter 2000
+
+ 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 2 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, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "winbindd.h"
+#include "sids.h"
+
+/* Convert a string */
+
+enum winbindd_result winbindd_lookupsid(struct winbindd_cli_state *state)
+{
+ extern DOM_SID global_sid_Builtin;
+ enum SID_NAME_USE type;
+ DOM_SID sid, tmp_sid;
+ uint32 rid;
+ fstring name;
+
+ DEBUG(3, ("[%5d]: lookupsid %s\n", state->pid,
+ state->request.data.sid));
+
+ /* Lookup sid from PDC using lsa_lookup_sids() */
+
+ string_to_sid(&sid, state->request.data.sid);
+
+ /* Don't look up BUILTIN sids */
+
+ sid_copy(&tmp_sid, &sid);
+ sid_split_rid(&tmp_sid, &rid);
+
+ if (sid_equal(&tmp_sid, &global_sid_Builtin)) {
+ return WINBINDD_ERROR;
+ }
+
+ /* Lookup the sid */
+
+ if (!winbindd_lookup_name_by_sid(&sid, name, &type)) {
+ return WINBINDD_ERROR;
+ }
+
+ string_sub(name, "\\", lp_winbind_separator(), sizeof(fstring));
+ fstrcpy(state->response.data.name.name, name);
+ state->response.data.name.type = type;
+
+ return WINBINDD_OK;
+}
+
+/* Convert a sid to a string */
+
+enum winbindd_result winbindd_lookupname(struct winbindd_cli_state *state)
+{
+ enum SID_NAME_USE type;
+ fstring sid_str, name_domain, name_user, name;
+ DOM_SID sid;
+
+ DEBUG(3, ("[%5d]: lookupname %s\n", state->pid,
+ state->request.data.name));
+
+ parse_domain_user(state->request.data.name, name_domain, name_user);
+
+ snprintf(name, sizeof(name), "%s\\%s", name_domain, name_user);
+
+ /* Lookup name from PDC using lsa_lookup_names() */
+
+ if (!winbindd_lookup_sid_by_name(name, &sid, &type)) {
+ return WINBINDD_ERROR;
+ }
+
+ sid_to_string(sid_str, &sid);
+ fstrcpy(state->response.data.sid.sid, sid_str);
+ state->response.data.sid.type = type;
+
+ return WINBINDD_OK;
+}
+
+/* Convert a sid to a uid. We assume we only have one rid attached to the
+ sid. */
+
+enum winbindd_result winbindd_sid_to_uid(struct winbindd_cli_state *state)
+{
+ DOM_SID sid;
+ uint32 user_rid;
+ struct winbindd_domain *domain;
+
+ DEBUG(3, ("[%5d]: sid to uid %s\n", state->pid,
+ state->request.data.sid));
+
+ /* Split sid into domain sid and user rid */
+
+ string_to_sid(&sid, state->request.data.sid);
+ sid_split_rid(&sid, &user_rid);
+
+ /* Find domain this sid belongs to */
+
+ if ((domain = find_domain_from_sid(&sid)) == NULL) {
+ fstring sid_str;
+
+ sid_to_string(sid_str, &sid);
+ DEBUG(1, ("Could not find domain for sid %s\n", sid_str));
+ return WINBINDD_ERROR;
+ }
+
+ /* Find uid for this sid and return it */
+
+ if (!winbindd_idmap_get_uid_from_rid(domain->name, user_rid,
+ &state->response.data.uid)) {
+ DEBUG(1, ("Could not get uid for sid %s\n",
+ state->request.data.sid));
+ return WINBINDD_ERROR;
+ }
+
+ return WINBINDD_OK;
+}
+
+/* Convert a sid to a gid. We assume we only have one rid attached to the
+ sid.*/
+
+enum winbindd_result winbindd_sid_to_gid(struct winbindd_cli_state *state)
+{
+ DOM_SID sid;
+ uint32 group_rid;
+ struct winbindd_domain *domain;
+
+ DEBUG(3, ("[%5d]: sid to gid %s\n", state->pid,
+ state->request.data.sid));
+
+ /* Split sid into domain sid and user rid */
+
+ string_to_sid(&sid, state->request.data.sid);
+ sid_split_rid(&sid, &group_rid);
+
+ /* Find domain this sid belongs to */
+
+ if ((domain = find_domain_from_sid(&sid)) == NULL) {
+ fstring sid_str;
+
+ sid_to_string(sid_str, &sid);
+ DEBUG(1, ("Could not find domain for sid %s\n", sid_str));
+ return WINBINDD_ERROR;
+ }
+
+ /* Find uid for this sid and return it */
+
+ if (!winbindd_idmap_get_gid_from_rid(domain->name, group_rid,
+ &state->response.data.gid)) {
+ DEBUG(1, ("Could not get gid for sid %s\n",
+ state->request.data.sid));
+ return WINBINDD_ERROR;
+ }
+
+ return WINBINDD_OK;
+}
+
+/* Convert a uid to a sid */
+
+enum winbindd_result winbindd_uid_to_sid(struct winbindd_cli_state *state)
+{
+ struct winbindd_domain *domain;
+ uint32 user_rid;
+ DOM_SID sid;
+
+ /* Bug out if the uid isn't in the winbind range */
+
+ if ((state->request.data.uid < server_state.uid_low ) ||
+ (state->request.data.uid > server_state.uid_high)) {
+ return WINBINDD_ERROR;
+ }
+
+ DEBUG(3, ("[%5d]: uid to sid %d\n", state->pid,
+ state->request.data.uid));
+
+ /* Lookup rid for this uid */
+
+ if (!winbindd_idmap_get_rid_from_uid(state->request.data.uid,
+ &user_rid, &domain)) {
+ DEBUG(1, ("Could not convert uid %d to rid\n",
+ state->request.data.uid));
+ return WINBINDD_ERROR;
+ }
+
+ /* Construct sid and return it */
+
+ sid_copy(&sid, &domain->sid);
+ sid_append_rid(&sid, user_rid);
+ sid_to_string(state->response.data.sid.sid, &sid);
+ state->response.data.sid.type = SID_NAME_USER;
+
+ return WINBINDD_OK;
+}
+
+/* Convert a gid to a sid */
+
+enum winbindd_result winbindd_gid_to_sid(struct winbindd_cli_state *state)
+{
+ struct winbindd_domain *domain;
+ uint32 group_rid;
+ DOM_SID sid;
+
+ /* Bug out if the gid isn't in the winbind range */
+
+ if ((state->request.data.gid < server_state.gid_low) ||
+ (state->request.data.gid > server_state.gid_high)) {
+ return WINBINDD_ERROR;
+ }
+
+ DEBUG(3, ("[%5d]: gid to sid %d\n", state->pid,
+ state->request.data.gid));
+
+ /* Lookup rid for this uid */
+
+ if (!winbindd_idmap_get_rid_from_gid(state->request.data.gid,
+ &group_rid, &domain)) {
+ DEBUG(1, ("Could not convert gid %d to rid\n",
+ state->request.data.gid));
+ return WINBINDD_ERROR;
+ }
+
+ /* Construct sid and return it */
+
+ sid_copy(&sid, &domain->sid);
+ sid_append_rid(&sid, group_rid);
+ sid_to_string(state->response.data.sid.sid, &sid);
+ state->response.data.sid.type = SID_NAME_DOM_GRP;
+
+ return WINBINDD_OK;
+}