iAdditional files for winbind merge.
authorTim Potter <tpot@samba.org>
Mon, 7 May 2001 05:03:40 +0000 (05:03 +0000)
committerTim Potter <tpot@samba.org>
Mon, 7 May 2001 05:03:40 +0000 (05:03 +0000)
source/nsswitch/pam_winbind.h [new file with mode: 0644]
source/nsswitch/winbindd_glue.c [new file with mode: 0644]
source/nsswitch/winbindd_misc.c [new file with mode: 0644]
source/nsswitch/winbindd_sid.c [new file with mode: 0644]

diff --git a/source/nsswitch/pam_winbind.h b/source/nsswitch/pam_winbind.h
new file mode 100644 (file)
index 0000000..85707cb
--- /dev/null
@@ -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/source/nsswitch/winbindd_glue.c b/source/nsswitch/winbindd_glue.c
new file mode 100644 (file)
index 0000000..ac8c60d
--- /dev/null
@@ -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/source/nsswitch/winbindd_misc.c b/source/nsswitch/winbindd_misc.c
new file mode 100644 (file)
index 0000000..182f983
--- /dev/null
@@ -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/source/nsswitch/winbindd_sid.c b/source/nsswitch/winbindd_sid.c
new file mode 100644 (file)
index 0000000..bc014f2
--- /dev/null
@@ -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;
+}