r3982: split out the sid -> uid/gid mapping routines into a ntvfs_sidmap
[kai/samba.git] / source4 / ntvfs / common / sidmap.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    mapping routines for SID <-> unix uid/gid
5
6    Copyright (C) Andrew Tridgell 2004
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24
25 /*
26   private context for sid mapping routines
27 */
28 struct sidmap_context {
29         void *samctx;
30 };
31
32 /*
33   open a sidmap context - use talloc_free to close
34 */
35 struct sidmap_context *sidmap_open(TALLOC_CTX *mem_ctx)
36 {
37         struct sidmap_context *sidmap;
38         sidmap = talloc_p(mem_ctx, struct sidmap_context);
39         if (sidmap == NULL) {
40                 return NULL;
41         }
42         sidmap->samctx = samdb_connect(sidmap);
43         if (sidmap->samctx == NULL) {
44                 talloc_free(sidmap);
45                 return NULL;
46         }
47
48         return sidmap;
49 }
50
51 /*
52   map a sid to a unix uid
53 */
54 NTSTATUS sidmap_sid_to_unixuid(struct sidmap_context *sidmap, 
55                                struct dom_sid *sid, uid_t *uid)
56 {
57         const char *attrs[] = { "sAMAccountName", "unixID", 
58                                 "unixName", "sAMAccountType", NULL };
59         int ret;
60         const char *s;
61         void *ctx;
62         struct ldb_message **res;
63         const char *sidstr;
64         uint_t atype;
65
66         ctx = talloc(sidmap, 0);
67         sidstr = dom_sid_string(ctx, sid);
68         if (sidstr == NULL) {
69                 talloc_free(ctx);
70                 return NT_STATUS_NO_MEMORY;
71         }
72
73         ret = samdb_search(sidmap->samctx, ctx, NULL, &res, attrs, 
74                            "objectSid=%s", sidstr);
75         if (ret != 1) {
76                 DEBUG(0,("sid_to_unixuid: unable to find sam record for sid %s\n", sidstr));
77                 talloc_free(ctx);
78                 return NT_STATUS_ACCESS_DENIED;
79         }
80
81         /* make sure its a user, not a group */
82         atype = samdb_result_uint(res[0], "sAMAccountType", 0);
83         if (atype && (!(atype & ATYPE_ACCOUNT))) {
84                 DEBUG(0,("sid_to_unixuid: sid %s is not an account!\n", sidstr));
85                 talloc_free(ctx);
86                 return NT_STATUS_ACCESS_DENIED;
87         }
88
89         /* first try to get the uid directly */
90         s = samdb_result_string(res[0], "unixID", NULL);
91         if (s != NULL) {
92                 *uid = strtoul(s, NULL, 0);
93                 talloc_free(ctx);
94                 return NT_STATUS_OK;
95         }
96
97         /* next try via the UnixName attribute */
98         s = samdb_result_string(res[0], "unixName", NULL);
99         if (s != NULL) {
100                 struct passwd *pwd = getpwnam(s);
101                 if (!pwd) {
102                         DEBUG(0,("unixName %s for sid %s does not exist as a local user\n", s, sidstr));
103                         talloc_free(ctx);
104                         return NT_STATUS_ACCESS_DENIED;
105                 }
106                 *uid = pwd->pw_uid;
107                 talloc_free(ctx);
108                 return NT_STATUS_OK;
109         }
110
111         /* finally try via the sAMAccountName attribute */
112         s = samdb_result_string(res[0], "sAMAccountName", NULL);
113         if (s != NULL) {
114                 struct passwd *pwd = getpwnam(s);
115                 if (!pwd) {
116                         DEBUG(0,("sAMAccountName '%s' for sid %s does not exist as a local user\n", s, sidstr));
117                         talloc_free(ctx);
118                         return NT_STATUS_ACCESS_DENIED;
119                 }
120                 *uid = pwd->pw_uid;
121                 talloc_free(ctx);
122                 return NT_STATUS_OK;
123         }
124
125         DEBUG(0,("sid_to_unixuid: no unixID, unixName or sAMAccountName for sid %s\n", sidstr));
126
127         talloc_free(ctx);
128         return NT_STATUS_ACCESS_DENIED;
129 }
130
131
132 /*
133   map a sid to a unix gid
134 */
135 NTSTATUS sidmap_sid_to_unixgid(struct sidmap_context *sidmap,
136                                struct dom_sid *sid, gid_t *gid)
137 {
138         const char *attrs[] = { "sAMAccountName", "unixID", 
139                                 "unixName", "sAMAccountType", NULL };
140         int ret;
141         const char *s;
142         void *ctx;
143         struct ldb_message **res;
144         const char *sidstr;
145         uint_t atype;
146
147         ctx = talloc(sidmap, 0);
148         sidstr = dom_sid_string(ctx, sid);
149         if (sidstr == NULL) {
150                 talloc_free(ctx);
151                 return NT_STATUS_NO_MEMORY;
152         }
153
154         ret = samdb_search(sidmap->samctx, ctx, NULL, &res, attrs, 
155                            "objectSid=%s", sidstr);
156         if (ret != 1) {
157                 DEBUG(0,("sid_to_unixgid: unable to find sam record for sid %s\n", sidstr));
158                 talloc_free(ctx);
159                 return NT_STATUS_ACCESS_DENIED;
160         }
161
162         /* make sure its not a user */
163         atype = samdb_result_uint(res[0], "sAMAccountType", 0);
164         if (atype && atype == ATYPE_NORMAL_ACCOUNT) {
165                 DEBUG(0,("sid_to_unixgid: sid %s is a ATYPE_NORMAL_ACCOUNT\n", sidstr));
166                 talloc_free(ctx);
167                 return NT_STATUS_ACCESS_DENIED;
168         }
169
170         /* first try to get the gid directly */
171         s = samdb_result_string(res[0], "unixID", NULL);
172         if (s != NULL) {
173                 *gid = strtoul(s, NULL, 0);
174                 talloc_free(ctx);
175                 return NT_STATUS_OK;
176         }
177
178         /* next try via the UnixName attribute */
179         s = samdb_result_string(res[0], "unixName", NULL);
180         if (s != NULL) {
181                 struct group *grp = getgrnam(s);
182                 if (!grp) {
183                         DEBUG(0,("unixName '%s' for sid %s does not exist as a local group\n", 
184                                  s, sidstr));
185                         talloc_free(ctx);
186                         return NT_STATUS_ACCESS_DENIED;
187                 }
188                 *gid = grp->gr_gid;
189                 talloc_free(ctx);
190                 return NT_STATUS_OK;
191         }
192
193         /* finally try via the sAMAccountName attribute */
194         s = samdb_result_string(res[0], "sAMAccountName", NULL);
195         if (s != NULL) {
196                 struct group *grp = getgrnam(s);
197                 if (!grp) {
198                         DEBUG(0,("sAMAccountName '%s' for sid %s does not exist as a local group\n", s, sidstr));
199                         talloc_free(ctx);
200                         return NT_STATUS_ACCESS_DENIED;
201                 }
202                 *gid = grp->gr_gid;
203                 talloc_free(ctx);
204                 return NT_STATUS_OK;
205         }
206
207         DEBUG(0,("sid_to_unixgid: no unixID, unixName or sAMAccountName for sid %s\n", 
208                  sidstr));
209
210         talloc_free(ctx);
211         return NT_STATUS_ACCESS_DENIED;
212 }