r25154: move winbindd code into winbindd/
[nivanova/samba-autobuild/.git] / source3 / winbindd / idmap_nss.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    idmap PASSDB backend
5
6    Copyright (C) Simo Sorce 2006
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 "winbindd.h"
24
25 #undef DBGC_CLASS
26 #define DBGC_CLASS DBGC_IDMAP
27
28 /*****************************
29  Initialise idmap database. 
30 *****************************/
31
32 static NTSTATUS idmap_nss_int_init(struct idmap_domain *dom)
33 {       
34         dom->initialized = True;
35         return NT_STATUS_OK;
36 }
37
38 /**********************************
39  lookup a set of unix ids. 
40 **********************************/
41
42 static NTSTATUS idmap_nss_unixids_to_sids(struct idmap_domain *dom, struct id_map **ids)
43 {
44         TALLOC_CTX *ctx;
45         int i;
46
47         if (! dom->initialized) {
48                 return NT_STATUS_UNSUCCESSFUL;
49         }
50
51         ctx = talloc_new(dom);
52         if ( ! ctx) {
53                 DEBUG(0, ("Out of memory!\n"));
54                 return NT_STATUS_NO_MEMORY;
55         }
56
57         for (i = 0; ids[i]; i++) {
58                 struct passwd *pw;
59                 struct group *gr;
60                 const char *name;
61                 enum lsa_SidType type;
62                 BOOL ret;
63                 
64                 switch (ids[i]->xid.type) {
65                 case ID_TYPE_UID:
66                         pw = getpwuid((uid_t)ids[i]->xid.id);
67
68                         if (!pw) {
69                                 ids[i]->status = ID_UNMAPPED;
70                                 continue;
71                         }
72                         name = pw->pw_name;
73                         break;
74                 case ID_TYPE_GID:
75                         gr = getgrgid((gid_t)ids[i]->xid.id);
76
77                         if (!gr) {
78                                 ids[i]->status = ID_UNMAPPED;
79                                 continue;
80                         }
81                         name = gr->gr_name;
82                         break;
83                 default: /* ?? */
84                         ids[i]->status = ID_UNKNOWN;
85                         continue;
86                 }
87
88                 /* by default calls to winbindd are disabled
89                    the following call will not recurse so this is safe */
90                 winbind_on();
91                 /* Lookup name from PDC using lsa_lookup_names() */
92                 ret = winbind_lookup_name(dom->name, name, ids[i]->sid, &type);
93                 winbind_off();
94
95                 if (!ret) {
96                         /* TODO: how do we know if the name is really not mapped,
97                          * or something just failed ? */
98                         ids[i]->status = ID_UNMAPPED;
99                         continue;
100                 }
101
102                 switch (type) {
103                 case SID_NAME_USER:
104                         if (ids[i]->xid.type == ID_TYPE_UID) {
105                                 ids[i]->status = ID_MAPPED;
106                         }
107                         break;
108
109                 case SID_NAME_DOM_GRP:
110                 case SID_NAME_ALIAS:
111                 case SID_NAME_WKN_GRP:
112                         if (ids[i]->xid.type == ID_TYPE_GID) {
113                                 ids[i]->status = ID_MAPPED;
114                         }
115                         break;
116
117                 default:
118                         ids[i]->status = ID_UNKNOWN;
119                         break;
120                 }
121         }
122
123
124         talloc_free(ctx);
125         return NT_STATUS_OK;
126 }
127
128 /**********************************
129  lookup a set of sids. 
130 **********************************/
131
132 static NTSTATUS idmap_nss_sids_to_unixids(struct idmap_domain *dom, struct id_map **ids)
133 {
134         TALLOC_CTX *ctx;
135         int i;
136
137         if (! dom->initialized) {
138                 return NT_STATUS_UNSUCCESSFUL;
139         }
140
141         ctx = talloc_new(dom);
142         if ( ! ctx) {
143                 DEBUG(0, ("Out of memory!\n"));
144                 return NT_STATUS_NO_MEMORY;
145         }
146
147         for (i = 0; ids[i]; i++) {
148                 struct passwd *pw;
149                 struct group *gr;
150                 enum lsa_SidType type;
151                 const char *dom_name = NULL;
152                 const char *name = NULL;
153                 BOOL ret;
154
155                 /* by default calls to winbindd are disabled
156                    the following call will not recurse so this is safe */
157                 winbind_on();
158                 ret = winbind_lookup_sid(ctx, ids[i]->sid, &dom_name, &name, &type);
159                 winbind_off();
160
161                 if (!ret) {
162                         /* TODO: how do we know if the name is really not mapped,
163                          * or something just failed ? */
164                         ids[i]->status = ID_UNMAPPED;
165                         continue;
166                 }
167
168                 switch (type) {
169                 case SID_NAME_USER:
170
171                         /* this will find also all lower case name and use username level */
172                         
173                         pw = Get_Pwnam(name);
174                         if (pw) {
175                                 ids[i]->xid.id = pw->pw_uid;
176                                 ids[i]->xid.type = ID_TYPE_UID;
177                                 ids[i]->status = ID_MAPPED;
178                         }
179                         break;
180
181                 case SID_NAME_DOM_GRP:
182                 case SID_NAME_ALIAS:
183                 case SID_NAME_WKN_GRP:
184
185                         gr = getgrnam(name);
186                         if (gr) {
187                                 ids[i]->xid.id = gr->gr_gid;
188                                 ids[i]->xid.type = ID_TYPE_GID;
189                                 ids[i]->status = ID_MAPPED;
190                         }
191                         break;
192
193                 default:
194                         ids[i]->status = ID_UNKNOWN;
195                         break;
196                 }
197         }
198
199         talloc_free(ctx);
200         return NT_STATUS_OK;
201 }
202
203 /**********************************
204  Close the idmap tdb instance
205 **********************************/
206
207 static NTSTATUS idmap_nss_close(struct idmap_domain *dom)
208 {
209         return NT_STATUS_OK;
210 }
211
212 static struct idmap_methods nss_methods = {
213
214         .init = idmap_nss_int_init,
215         .unixids_to_sids = idmap_nss_unixids_to_sids,
216         .sids_to_unixids = idmap_nss_sids_to_unixids,
217         .close_fn = idmap_nss_close
218 };
219
220 NTSTATUS idmap_nss_init(void)
221 {
222         return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "nss", &nss_methods);
223 }