brought the winbindd code into head
[kai/samba.git] / source / nsswitch / winbindd_idmap.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 2.0
4
5    Winbind daemon - user related function
6
7    Copyright (C) Tim Potter 2000
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "winbindd.h"
25
26 /* High water mark keys */
27
28 #define HWM_GROUP  "GROUP HWM"
29 #define HWM_USER   "USER HWM"
30
31 /* Globals */
32
33 static TDB_CONTEXT *idmap_tdb;
34
35 /* Allocate either a user or group id from the pool */
36
37 static BOOL allocate_id(int *id, BOOL isgroup)
38 {
39     int hwm;
40
41     /* Get current high water mark */
42
43     if ((hwm = tdb_get_int(idmap_tdb, isgroup ? HWM_GROUP : HWM_USER)) == -1) {
44         return False;
45     }
46
47     /* Return next available uid in list */
48
49     if ((isgroup && (hwm > server_state.gid_high)) ||
50         (!isgroup && (hwm > server_state.uid_high))) {
51         DEBUG(0, ("winbind %sid range full!\n", isgroup ? "g" : "u"));
52         return False;
53     }
54
55     if (id) {
56         *id = hwm;
57     }
58
59     hwm++;
60
61     /* Store new high water mark */
62
63     tdb_store_int(idmap_tdb, isgroup ? HWM_GROUP : HWM_USER, hwm);
64
65     return True;
66 }
67
68 /* Get an id from a rid */
69
70 static BOOL get_id_from_rid(char *domain_name, uint32 rid, int *id,
71                             BOOL isgroup)
72 {
73     TDB_DATA data, key;
74     fstring keystr;
75     BOOL result;
76
77     /* Check if rid is present in database */
78
79     slprintf(keystr, sizeof(keystr), "%s/%d", domain_name, rid);
80     
81     key.dptr = keystr;
82     key.dsize = strlen(keystr) + 1;
83
84     data = tdb_fetch(idmap_tdb, key);
85
86     if (data.dptr) {
87         fstring scanstr;
88         int the_id;
89
90         /* Parse and return existing uid */
91
92         fstrcpy(scanstr, isgroup ? "GID" : "UID");
93         fstrcat(scanstr, " %d");
94
95         if (sscanf(data.dptr, scanstr, &the_id) == 1) {
96
97             /* Store uid */
98
99             if (id) {
100                 *id = the_id;
101             }
102
103             result = True;
104         }
105
106         free(data.dptr);
107
108     } else {
109
110         /* Allocate a new id for this rid */
111
112         if (id && allocate_id(id, isgroup)) {
113             fstring keystr2;
114
115             /* Store new id */
116             
117             slprintf(keystr2, sizeof(keystr2), "%s %d", isgroup ? "GID" :
118                      "UID", *id);
119
120             data.dptr = keystr2;
121             data.dsize = strlen(keystr2) + 1;
122
123             tdb_store(idmap_tdb, key, data, TDB_REPLACE);
124             tdb_store(idmap_tdb, data, key, TDB_REPLACE);
125
126             result = True;
127         }
128     }
129
130     return result;
131 }
132
133 /* Get a uid from a user rid */
134
135 BOOL winbindd_idmap_get_uid_from_rid(char *domain_name, uint32 user_rid, 
136                                      uid_t *uid)
137 {
138     return get_id_from_rid(domain_name, user_rid, uid, False);
139 }
140
141 /* Get a gid from a group rid */
142
143 BOOL winbindd_idmap_get_gid_from_rid(char *domain_name, uint32 group_rid, 
144                                      gid_t *gid)
145 {
146     return get_id_from_rid(domain_name, group_rid, gid, True);
147 }
148
149 BOOL get_rid_from_id(int id, uint32 *rid, struct winbindd_domain **domain,
150                      BOOL isgroup)
151 {
152     TDB_DATA key, data;
153     fstring keystr;
154     BOOL result = False;
155
156     slprintf(keystr, sizeof(keystr), "%s %d", isgroup ? "GID" : "UID", id);
157
158     key.dptr = keystr;
159     key.dsize = strlen(keystr) + 1;
160
161     data = tdb_fetch(idmap_tdb, key);
162
163     if (data.dptr) {
164         char *p = data.dptr;
165         fstring domain_name;
166         uint32 the_rid;
167
168         if (next_token(&p, domain_name, "/", sizeof(fstring))) {
169
170             the_rid = atoi(p);
171
172             if (rid) {
173                 *rid = the_rid;
174             }
175
176             if (domain) {
177                 *domain = find_domain_from_name(domain_name);
178             }
179
180             result = True;
181         }
182             
183         free(data.dptr);
184     }
185
186     return result;
187 }
188
189 /* Get a user rid from a uid */
190
191 BOOL winbindd_idmap_get_rid_from_uid(uid_t uid, uint32 *user_rid,
192                                      struct winbindd_domain **domain)
193 {
194     return get_rid_from_id((int)uid, user_rid, domain, False);
195 }
196
197 /* Get a group rid from a gid */
198
199 BOOL winbindd_idmap_get_rid_from_gid(gid_t gid, uint32 *group_rid, 
200                                      struct winbindd_domain **domain)
201 {
202     return get_rid_from_id((int)gid, group_rid, domain, True);
203 }
204
205 /* Initialise idmap database */
206
207 BOOL winbindd_idmap_init(void)
208 {
209     /* Open tdb cache */
210
211     if (!(idmap_tdb = tdb_open(lock_path("winbindd_idmap.tdb"), 0,
212                                TDB_NOLOCK | TDB_NOMMAP, 
213                                O_RDWR | O_CREAT, 0600))) {
214         DEBUG(0, ("Unable to open idmap database\n"));
215         return False;
216     }
217
218      /* Create high water marks for group and user id */
219
220     if (tdb_get_int(idmap_tdb, HWM_USER) == -1) {
221         if (tdb_store_int(idmap_tdb, HWM_USER, server_state.uid_low) == -1) {
222             DEBUG(0, ("Unable to initialise user hwm in idmap database\n"));
223             return False;
224         }
225     }
226
227     if (tdb_get_int(idmap_tdb, HWM_GROUP) == -1) {
228         if (tdb_store_int(idmap_tdb, HWM_GROUP, server_state.gid_low) == -1) {
229             DEBUG(0, ("Unable to initialise group hwm in idmap database\n"));
230             return False;
231         }
232     }
233
234     return True;   
235 }