e0634681de1691a3a82330426029b79e241d1b26
[ira/wip.git] / source3 / sam / idmap.c
1 /* 
2    Unix SMB/CIFS implementation.
3    ID Mapping
4    Copyright (C) Tim Potter 2000
5    Copyright (C) Anthony Liguori <aliguor@us.ibm.com>   2003
6    Copyright (C) Simo Sorce 2003
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 #include "includes.h"
23
24 #undef DBGC_CLASS
25 #define DBGC_CLASS DBGC_IDMAP
26
27 static struct {
28
29         const char *name;
30         /* Function to create a member of the idmap_methods list */
31         NTSTATUS (*reg_meth)(struct idmap_methods **methods);
32         struct idmap_methods *methods;
33
34 } remote_idmap_functions[] = {
35         { NULL, NULL, NULL }
36 };
37
38 static struct idmap_methods *local_map;
39 static struct idmap_methods *remote_map;
40
41 static void lazy_initialize_idmap(void)
42 {
43         static BOOL initialized = False;
44         if (initialized) return;
45         idmap_init();
46         initialized = True;
47 }
48
49
50
51 static struct idmap_methods *get_methods(const char *name)
52 {
53         int i = 0;
54         struct idmap_methods *ret = NULL;
55
56         while (remote_idmap_functions[i].name && strcmp(remote_idmap_functions[i].name, name)) {
57                 i++;
58         }
59
60         if (remote_idmap_functions[i].name) {
61
62                 if (!remote_idmap_functions[i].methods) {
63                         remote_idmap_functions[i].reg_meth(&remote_idmap_functions[i].methods);
64                 }
65
66                 ret = remote_idmap_functions[i].methods;
67         }
68
69         return ret;
70 }
71
72 /* Initialize backend */
73 BOOL idmap_init(void)
74 {
75         const char *remote_backend = lp_idmap_backend();
76
77         if (!local_map) {
78                 idmap_reg_tdb(&local_map);
79                 if (NT_STATUS_IS_ERR(local_map->init())) {
80                         DEBUG(0, ("idmap_init: could not load or create local backend!\n"));
81                         return False;
82                 }
83         }
84         
85         if (!remote_map && remote_backend && *remote_backend != 0) {
86                 DEBUG(3, ("idmap_init: using '%s' as remote backend\n", remote_backend));
87                 
88                 remote_map = get_methods(remote_backend);
89                 if (!remote_map) {
90                         DEBUG(0, ("idmap_init: could not load remote backend '%s'\n", remote_backend));
91                         return False;
92                 }
93                 remote_map->init();
94         }
95
96         return True;
97 }
98
99 NTSTATUS idmap_set_mapping(const DOM_SID *sid, unid_t id, int id_type)
100 {
101         NTSTATUS ret;
102
103         lazy_initialize_idmap();
104
105         if (!lp_idmap_only()) {
106                 if (id_type & ID_USERID) {
107                         uid_t low, high;
108                         if (!lp_idmap_uid(&low, &high)) {
109                                 DEBUG(0, ("idmap uid range missing or invalid\n"));
110                                 DEBUGADD(0, ("idmap will be unable to map SIDs\n"));
111                                 return NT_STATUS_UNSUCCESSFUL;
112                         }
113                         if (low > id.uid || high < id.uid) {
114                                 DEBUG(0, ("uid not in range and idmap only is flase - not storing the mapping\n"));
115                                 return NT_STATUS_UNSUCCESSFUL;
116                         }
117                 } else if (id_type & ID_GROUPID) {
118                         gid_t low, high;
119                         if (!lp_idmap_gid(&low, &high)) {
120                                 DEBUG(0, ("idmap gid range missing or invalid\n"));
121                                 DEBUGADD(0, ("idmap will be unable to map SIDs\n"));
122                                 return NT_STATUS_UNSUCCESSFUL;
123                         }
124                         if (low > id.gid || high < id.gid) {
125                                 DEBUG(0, ("uid not in range and idmap only is flase - not storing the mapping\n"));
126                                 return NT_STATUS_UNSUCCESSFUL;
127                         }
128                 } else {
129                         DEBUG(0, ("Wrong ID Type, mapping failed!"));
130                         return NT_STATUS_UNSUCCESSFUL;
131                 }
132         }
133         
134         ret = local_map->set_mapping(sid, id, id_type);
135         if (NT_STATUS_IS_ERR(ret)) {
136                 DEBUG (0, ("idmap_set_mapping: Error, unable to modify local cache!\n"));
137                 DEBUGADD(0, ("Error: %s", nt_errstr(ret)));
138                 return ret;
139         }
140
141         /* Being able to update the remote cache is seldomly right.
142            Generally this is a forbidden operation. */
143         if (!(id_type & ID_CACHE) && (remote_map != NULL)) {
144                 remote_map->set_mapping(sid, id, id_type);
145                 if (NT_STATUS_IS_ERR(ret)) {
146                         DEBUG (0, ("idmap_set_mapping: Error, unable to modify remote cache!\n"));
147                         DEBUGADD(0, ("Error: %s", nt_errstr(ret)));
148                 }
149         }
150
151         return ret;
152 }
153
154 /* Get ID from SID */
155 NTSTATUS idmap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *sid)
156 {
157         NTSTATUS ret;
158         int loc_type;
159
160         lazy_initialize_idmap();
161
162         loc_type = *id_type;
163         if (remote_map) { /* We have a central remote idmap */
164                 loc_type |= ID_NOMAP;
165         }
166         ret = local_map->get_id_from_sid(id, &loc_type, sid);
167         if (NT_STATUS_IS_ERR(ret)) {
168                 if (remote_map) {
169                         ret = remote_map->get_id_from_sid(id, id_type, sid);
170                         if (NT_STATUS_IS_ERR(ret)) {
171                                 DEBUG(3, ("idmap_get_id_from_sid: error fetching id!\n"));
172                                 return ret;
173                         } else {
174                                 loc_type |= ID_CACHE;
175                                 idmap_set_mapping(sid, *id, loc_type);
176                         }
177                 }
178         } else {
179                 *id_type = loc_type & ID_TYPEMASK;
180         }
181
182         return ret;
183 }
184
185 /* Get SID from ID */
186 NTSTATUS idmap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type)
187 {
188         NTSTATUS ret;
189         int loc_type;
190
191         lazy_initialize_idmap();
192
193         loc_type = id_type;
194         if (remote_map) {
195                 loc_type = id_type | ID_NOMAP;
196         }
197         ret = local_map->get_sid_from_id(sid, id, loc_type);
198         if (NT_STATUS_IS_ERR(ret)) {
199                 if (remote_map) {
200                         ret = remote_map->get_sid_from_id(sid, id, id_type);
201                         if (NT_STATUS_IS_ERR(ret)) {
202                                 DEBUG(3, ("idmap_get_sid_from_id: unable to fetch sid!\n"));
203                                 return ret;
204                         } else {
205                                 loc_type |= ID_CACHE;
206                                 idmap_set_mapping(sid, id, loc_type);
207                         }
208                 }
209         }
210
211         return ret;
212 }
213
214 /* Close backend */
215 NTSTATUS idmap_close(void)
216 {
217         NTSTATUS ret;
218
219         ret = local_map->close();
220         if (NT_STATUS_IS_ERR(ret)) {
221                 DEBUG(3, ("idmap_close: failed to close local cache!\n"));
222         }
223
224         if (remote_map) {
225                 ret = remote_map->close();
226                 if (NT_STATUS_IS_ERR(ret)) {
227                         DEBUG(3, ("idmap_close: failed to close remote idmap repository!\n"));
228                 }
229         }
230
231         return ret;
232 }
233
234 /* Dump backend status */
235 void idmap_status(void)
236 {
237         lazy_initialize_idmap();
238
239         local_map->status();
240         if (remote_map) remote_map->status();
241 }
242