s4-drs: implement more of DsUpdateRefs
[nivanova/samba-autobuild/.git] / source4 / rpc_server / unixinfo / dcesrv_unixinfo.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    endpoint server for the unixinfo pipe
5
6    Copyright (C) Volker Lendecke 2005
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 3 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, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "rpc_server/dcerpc_server.h"
24 #include "librpc/gen_ndr/ndr_unixinfo.h"
25 #include "libcli/wbclient/wbclient.h"
26 #include "system/passwd.h"
27
28 static NTSTATUS dcerpc_unixinfo_bind(struct dcesrv_call_state *dce_call,
29                                      const struct dcesrv_interface *iface)
30 {
31         struct wbc_context *wbc_ctx;
32
33         wbc_ctx = wbc_init(dce_call->context, dce_call->msg_ctx,
34                            dce_call->event_ctx);
35         NT_STATUS_HAVE_NO_MEMORY(wbc_ctx);
36
37         dce_call->context->private_data = wbc_ctx;
38
39         return NT_STATUS_OK;
40 }
41
42 #define DCESRV_INTERFACE_UNIXINFO_BIND dcerpc_unixinfo_bind
43
44 static NTSTATUS dcesrv_unixinfo_SidToUid(struct dcesrv_call_state *dce_call,
45                                   TALLOC_CTX *mem_ctx,
46                                   struct unixinfo_SidToUid *r)
47 {
48         NTSTATUS status;
49         struct wbc_context *wbc_ctx = talloc_get_type_abort(
50                                                 dce_call->context->private_data,
51                                                 struct wbc_context);
52         struct id_mapping *ids;
53         struct composite_context *ctx;
54
55         DEBUG(5, ("dcesrv_unixinfo_SidToUid called\n"));
56
57         ids = talloc(mem_ctx, struct  id_mapping);
58         NT_STATUS_HAVE_NO_MEMORY(ids);
59
60         ids->sid = &r->in.sid;
61         ids->status = NT_STATUS_NONE_MAPPED;
62         ids->unixid = NULL;
63         ctx = wbc_sids_to_xids_send(wbc_ctx, ids, 1, ids);
64         NT_STATUS_HAVE_NO_MEMORY(ctx);
65
66         status = wbc_sids_to_xids_recv(ctx, &ids);
67         NT_STATUS_NOT_OK_RETURN(status);
68
69         if (ids->unixid->type == ID_TYPE_BOTH ||
70             ids->unixid->type == ID_TYPE_UID) {
71                 *r->out.uid = ids->unixid->id;
72                 return NT_STATUS_OK;
73         } else {
74                 return NT_STATUS_INVALID_SID;
75         }
76 }
77
78 static NTSTATUS dcesrv_unixinfo_UidToSid(struct dcesrv_call_state *dce_call,
79                                   TALLOC_CTX *mem_ctx,
80                                   struct unixinfo_UidToSid *r)
81 {
82         struct wbc_context *wbc_ctx = talloc_get_type_abort(
83                                                 dce_call->context->private_data,
84                                                 struct wbc_context);
85         struct id_mapping *ids;
86         struct composite_context *ctx;
87         uint32_t uid;
88         NTSTATUS status;
89
90         DEBUG(5, ("dcesrv_unixinfo_UidToSid called\n"));
91
92         uid = r->in.uid;        /* This cuts uid to 32 bit */
93         if ((uint64_t)uid != r->in.uid) {
94                 DEBUG(10, ("uid out of range\n"));
95                 return NT_STATUS_INVALID_PARAMETER;
96         }
97
98         ids = talloc(mem_ctx, struct id_mapping);
99         NT_STATUS_HAVE_NO_MEMORY(ids);
100
101         ids->sid = NULL;
102         ids->status = NT_STATUS_NONE_MAPPED;
103         ids->unixid = talloc(ids, struct unixid);
104         NT_STATUS_HAVE_NO_MEMORY(ids->unixid);
105
106         ids->unixid->id = uid;
107         ids->unixid->type = ID_TYPE_UID;
108
109         ctx = wbc_xids_to_sids_send(wbc_ctx, ids, 1, ids);
110         NT_STATUS_HAVE_NO_MEMORY(ctx);
111
112         status = wbc_xids_to_sids_recv(ctx, &ids);
113         NT_STATUS_NOT_OK_RETURN(status);
114
115         r->out.sid = ids->sid;
116         return NT_STATUS_OK;
117 }
118
119 static NTSTATUS dcesrv_unixinfo_SidToGid(struct dcesrv_call_state *dce_call,
120                                   TALLOC_CTX *mem_ctx,
121                                   struct unixinfo_SidToGid *r)
122 {
123         NTSTATUS status;
124         struct wbc_context *wbc_ctx = talloc_get_type_abort(
125                                                 dce_call->context->private_data,
126                                                 struct wbc_context);
127         struct id_mapping *ids;
128         struct composite_context *ctx;
129
130         DEBUG(5, ("dcesrv_unixinfo_SidToGid called\n"));
131
132         ids = talloc(mem_ctx, struct  id_mapping);
133         NT_STATUS_HAVE_NO_MEMORY(ids);
134
135         ids->sid = &r->in.sid;
136         ids->status = NT_STATUS_NONE_MAPPED;
137         ids->unixid = NULL;
138         ctx = wbc_sids_to_xids_send(wbc_ctx, ids, 1, ids);
139         NT_STATUS_HAVE_NO_MEMORY(ctx);
140
141         status = wbc_sids_to_xids_recv(ctx, &ids);
142         NT_STATUS_NOT_OK_RETURN(status);
143
144         if (ids->unixid->type == ID_TYPE_BOTH ||
145             ids->unixid->type == ID_TYPE_GID) {
146                 *r->out.gid = ids->unixid->id;
147                 return NT_STATUS_OK;
148         } else {
149                 return NT_STATUS_INVALID_SID;
150         }
151 }
152
153 static NTSTATUS dcesrv_unixinfo_GidToSid(struct dcesrv_call_state *dce_call,
154                                   TALLOC_CTX *mem_ctx,
155                                   struct unixinfo_GidToSid *r)
156 {
157         struct wbc_context *wbc_ctx = talloc_get_type_abort(
158                                                 dce_call->context->private_data,
159                                                 struct wbc_context);
160         struct id_mapping *ids;
161         struct composite_context *ctx;
162         uint32_t gid;
163         NTSTATUS status;
164
165         DEBUG(5, ("dcesrv_unixinfo_GidToSid called\n"));
166
167         gid = r->in.gid;        /* This cuts gid to 32 bit */
168         if ((uint64_t)gid != r->in.gid) {
169                 DEBUG(10, ("gid out of range\n"));
170                 return NT_STATUS_INVALID_PARAMETER;
171         }
172
173         ids = talloc(mem_ctx, struct id_mapping);
174         NT_STATUS_HAVE_NO_MEMORY(ids);
175
176         ids->sid = NULL;
177         ids->status = NT_STATUS_NONE_MAPPED;
178         ids->unixid = talloc(ids, struct unixid);
179         NT_STATUS_HAVE_NO_MEMORY(ids->unixid);
180
181         ids->unixid->id = gid;
182         ids->unixid->type = ID_TYPE_GID;
183
184         ctx = wbc_xids_to_sids_send(wbc_ctx, ids, 1, ids);
185         NT_STATUS_HAVE_NO_MEMORY(ctx);
186
187         status = wbc_xids_to_sids_recv(ctx, &ids);
188         NT_STATUS_NOT_OK_RETURN(status);
189
190         r->out.sid = ids->sid;
191         return NT_STATUS_OK;
192 }
193
194 static NTSTATUS dcesrv_unixinfo_GetPWUid(struct dcesrv_call_state *dce_call,
195                                   TALLOC_CTX *mem_ctx,
196                                   struct unixinfo_GetPWUid *r)
197 {
198         int i;
199
200         *r->out.count = 0;
201
202         r->out.infos = talloc_zero_array(mem_ctx, struct unixinfo_GetPWUidInfo,
203                                          *r->in.count);
204         NT_STATUS_HAVE_NO_MEMORY(r->out.infos);
205         *r->out.count = *r->in.count;
206
207         for (i=0; i < *r->in.count; i++) {
208                 uid_t uid;
209                 struct passwd *pwd;
210
211                 uid = r->in.uids[i];
212                 pwd = getpwuid(uid);
213                 if (pwd == NULL) {
214                         DEBUG(10, ("uid %d not found\n", uid));
215                         r->out.infos[i].homedir = "";
216                         r->out.infos[i].shell = "";
217                         r->out.infos[i].status = NT_STATUS_NO_SUCH_USER;
218                         continue;
219                 }
220
221                 r->out.infos[i].homedir = talloc_strdup(mem_ctx, pwd->pw_dir);
222                 r->out.infos[i].shell = talloc_strdup(mem_ctx, pwd->pw_shell);
223
224                 if ((r->out.infos[i].homedir == NULL) ||
225                     (r->out.infos[i].shell == NULL)) {
226                         r->out.infos[i].homedir = "";
227                         r->out.infos[i].shell = "";
228                         r->out.infos[i].status = NT_STATUS_NO_MEMORY;
229                         continue;
230                 }
231
232                 r->out.infos[i].status = NT_STATUS_OK;
233         }
234
235         return NT_STATUS_OK;
236 }
237
238 /* include the generated boilerplate */
239 #include "librpc/gen_ndr/ndr_unixinfo_s.c"