1 | /*
|
---|
2 | * Unix SMB/CIFS implementation.
|
---|
3 | * cacusermgr user implementation.
|
---|
4 | *
|
---|
5 | * Copyright (C) Chris Nicholls 2005
|
---|
6 | *
|
---|
7 | * This program is free software; you can redistribute it and/or modify it
|
---|
8 | * under the terms of the GNU General Public License as published by the
|
---|
9 | * Free Software Foundation; either version 2 of the License, or (at your
|
---|
10 | * option) any later version.
|
---|
11 | *
|
---|
12 | * This program is distributed in the hope that it will be useful, but WITHOUT
|
---|
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
---|
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
---|
15 | * more details.
|
---|
16 | *
|
---|
17 | * You should have received a copy of the GNU General Public License along with
|
---|
18 | * this program; if not, write to the Free Software Foundation, Inc., 675
|
---|
19 | * Mass Ave, Cambridge, MA 02139, USA. */
|
---|
20 |
|
---|
21 | #include "cacusermgr.h"
|
---|
22 |
|
---|
23 | void print_user_info(CacUserInfo *info) {
|
---|
24 | printf("\n");
|
---|
25 | printf(" User Name : %s\n", info->username);
|
---|
26 | printf(" Full Name : %s\n", info->full_name);
|
---|
27 | printf(" Home Dir : %s\n", info->home_dir);
|
---|
28 | printf(" Home Drive : %s\n", info->home_drive);
|
---|
29 | printf(" Profile Path : %s\n", info->profile_path);
|
---|
30 | printf(" Logon Script : %s\n", info->logon_script);
|
---|
31 | printf(" Description : %s\n", info->description);
|
---|
32 | printf(" Workstations : %s\n", info->workstations);
|
---|
33 | printf(" Remote Dial : %s\n", info->dial);
|
---|
34 |
|
---|
35 | printf(" Logon Time : %s\n", http_timestring(info->logon_time));
|
---|
36 | printf(" Logoff Time : %s\n", http_timestring(info->logoff_time));
|
---|
37 | printf(" Kickoff Time : %s\n", http_timestring(info->kickoff_time));
|
---|
38 | printf(" Pass last set : %s\n", http_timestring(info->pass_last_set_time));
|
---|
39 | printf(" Pass can set : %s\n", http_timestring(info->pass_can_change_time));
|
---|
40 | printf(" Pass must set : %s\n", http_timestring(info->pass_must_change_time));
|
---|
41 |
|
---|
42 | printf(" User RID : 0x%x\n", info->rid);
|
---|
43 | printf(" Group RID : 0x%x\n", info->group_rid);
|
---|
44 | printf(" User Type : ");
|
---|
45 |
|
---|
46 | if(info->acb_mask & ACB_NORMAL)
|
---|
47 | printf("Normal User\n");
|
---|
48 | else if(info->acb_mask & ACB_TEMPDUP)
|
---|
49 | printf("Temporary Duplicate Account\n");
|
---|
50 | else if(info->acb_mask & ACB_DOMTRUST)
|
---|
51 | printf("Inter-Domain Trust Account\n");
|
---|
52 | else if(info->acb_mask & ACB_WSTRUST)
|
---|
53 | printf("Workstation Trust Account\n");
|
---|
54 | else if(info->acb_mask & ACB_SVRTRUST)
|
---|
55 | printf("Server Trust Account\n");
|
---|
56 | else
|
---|
57 | printf("\n");
|
---|
58 |
|
---|
59 | printf(" Disabled : %s\n", (info->acb_mask & ACB_DISABLED) ? "Yes" : "No");
|
---|
60 | printf(" Locked : %s\n", (info->acb_mask & ACB_AUTOLOCK) ? "Yes" : "No");
|
---|
61 | printf(" Pass Expires : %s\n", (info->acb_mask & ACB_PWNOEXP) ? "No" : "Yes");
|
---|
62 | printf(" Pass Required : %s\n", (info->acb_mask & ACB_PWNOTREQ) ? "No" : "Yes");
|
---|
63 |
|
---|
64 | }
|
---|
65 |
|
---|
66 | CacUserInfo *modify_user_info(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *user_hnd) {
|
---|
67 | CacUserInfo *info = NULL;
|
---|
68 | fstring tmp;
|
---|
69 |
|
---|
70 | struct SamGetUserInfo getinfo;
|
---|
71 | struct SamSetUserInfo setinfo;
|
---|
72 |
|
---|
73 | ZERO_STRUCT(getinfo);
|
---|
74 | ZERO_STRUCT(setinfo);
|
---|
75 |
|
---|
76 | getinfo.in.user_hnd = user_hnd;
|
---|
77 |
|
---|
78 | if(!cac_SamGetUserInfo(hnd, mem_ctx, &getinfo)) {
|
---|
79 | printerr("Could not get user info.", hnd->status);
|
---|
80 | return NULL;
|
---|
81 | }
|
---|
82 |
|
---|
83 | info = getinfo.out.info;
|
---|
84 |
|
---|
85 | printf("\n");
|
---|
86 | printf(" User Name [%s]: ", info->username);
|
---|
87 | mgr_getline(tmp);
|
---|
88 | if(tmp[0] != '\0')
|
---|
89 | info->username = talloc_strdup(mem_ctx, tmp);
|
---|
90 |
|
---|
91 | printf(" Full Name [%s]: ", info->full_name);
|
---|
92 | mgr_getline(tmp);
|
---|
93 | if(tmp[0] != '\0')
|
---|
94 | info->full_name = talloc_strdup(mem_ctx, tmp);
|
---|
95 |
|
---|
96 | printf(" Description [%s]: ", info->description);
|
---|
97 | mgr_getline(tmp);
|
---|
98 | if(tmp[0] != '\0')
|
---|
99 | info->description = talloc_strdup(mem_ctx, tmp);
|
---|
100 |
|
---|
101 | printf(" Home Dir [%s]: ", info->home_dir);
|
---|
102 | mgr_getline(tmp);
|
---|
103 | if(tmp[0] != '\0')
|
---|
104 | info->home_dir = talloc_strdup(mem_ctx, tmp);
|
---|
105 |
|
---|
106 | printf(" Home Drive [%s]: ", info->home_drive);
|
---|
107 | mgr_getline(tmp);
|
---|
108 | if(tmp[0] != '\0')
|
---|
109 | info->home_drive = talloc_strdup(mem_ctx, tmp);
|
---|
110 |
|
---|
111 | printf(" Profile Path [%s]: ", info->profile_path);
|
---|
112 | mgr_getline(tmp);
|
---|
113 | if(tmp[0] != '\0')
|
---|
114 | info->profile_path = talloc_strdup(mem_ctx, tmp);
|
---|
115 |
|
---|
116 | printf(" Logon Script [%s]: ", info->logon_script);
|
---|
117 | mgr_getline(tmp);
|
---|
118 | if(tmp[0] != '\0')
|
---|
119 | info->logon_script = talloc_strdup(mem_ctx, tmp);
|
---|
120 |
|
---|
121 | printf(" Workstations [%s]: ", info->workstations);
|
---|
122 | mgr_getline(tmp);
|
---|
123 | if(tmp[0] != '\0')
|
---|
124 | info->workstations = talloc_strdup(mem_ctx, tmp);
|
---|
125 |
|
---|
126 | printf(" Remote Dial [%s]: ", info->dial);
|
---|
127 | mgr_getline(tmp);
|
---|
128 | if(tmp[0] != '\0')
|
---|
129 | info->dial = talloc_strdup(mem_ctx, tmp);
|
---|
130 |
|
---|
131 | printf(" Disabled [%s] (y/n): ", (info->acb_mask & ACB_DISABLED) ? "Yes" : "No");
|
---|
132 | mgr_getline(tmp);
|
---|
133 | if(tmp[0] == 'y' || tmp[0] == 'Y')
|
---|
134 | info->acb_mask |= ACB_DISABLED;
|
---|
135 | else if(tmp[0] == 'n' || tmp[0] == 'N')
|
---|
136 | info->acb_mask ^= (info->acb_mask & ACB_DISABLED) ? ACB_DISABLED : 0x0;
|
---|
137 |
|
---|
138 | printf(" Pass Expires [%s] (y/n): ", (info->acb_mask & ACB_PWNOEXP) ? "No" : "Yes");
|
---|
139 | mgr_getline(tmp);
|
---|
140 | if(tmp[0] == 'n' || tmp[0] == 'N')
|
---|
141 | info->acb_mask |= ACB_PWNOEXP;
|
---|
142 | else if(tmp[0] == 'y' || tmp[0] == 'Y')
|
---|
143 | info->acb_mask ^= (info->acb_mask & ACB_PWNOEXP) ? ACB_PWNOEXP : 0x0;
|
---|
144 |
|
---|
145 | printf(" Pass Required [%s] (y/n): ", (info->acb_mask & ACB_PWNOTREQ) ? "No" : "Yes");
|
---|
146 | mgr_getline(tmp);
|
---|
147 | if(tmp[0] == 'n' || tmp[0] == 'N')
|
---|
148 | info->acb_mask |= ACB_PWNOTREQ;
|
---|
149 | else if(tmp[0] == 'y' || tmp[0] == 'Y')
|
---|
150 | info->acb_mask ^= (info->acb_mask & ACB_PWNOTREQ) ? ACB_PWNOTREQ : 0x0;
|
---|
151 |
|
---|
152 | setinfo.in.user_hnd = user_hnd;
|
---|
153 | setinfo.in.info = info;
|
---|
154 |
|
---|
155 | if(!cac_SamSetUserInfo(hnd, mem_ctx, &setinfo)) {
|
---|
156 | printerr("Could not set user info.", hnd->status);
|
---|
157 | }
|
---|
158 |
|
---|
159 | return info;
|
---|
160 | }
|
---|
161 |
|
---|
162 | void add_user_to_group(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, CacUserInfo *info, POLICY_HND *dom_hnd) {
|
---|
163 | int rid_type = 0;
|
---|
164 |
|
---|
165 | char *tmp = NULL;
|
---|
166 |
|
---|
167 | struct SamOpenGroup og;
|
---|
168 | struct SamAddGroupMember add;
|
---|
169 |
|
---|
170 | ZERO_STRUCT(og);
|
---|
171 | ZERO_STRUCT(add);
|
---|
172 |
|
---|
173 | printf("Group RID or Name:");
|
---|
174 |
|
---|
175 | og.in.dom_hnd = dom_hnd;
|
---|
176 | og.in.access = MAXIMUM_ALLOWED_ACCESS;
|
---|
177 | rid_type = rid_or_name(hnd, mem_ctx, dom_hnd, &og.in.rid, &tmp);
|
---|
178 |
|
---|
179 | if(!cac_SamOpenGroup(hnd, mem_ctx, &og)) {
|
---|
180 | printerr("Could not open group.", hnd->status);
|
---|
181 | return;
|
---|
182 | }
|
---|
183 |
|
---|
184 | add.in.group_hnd = og.out.group_hnd;
|
---|
185 | add.in.rid = info->rid;
|
---|
186 |
|
---|
187 | if(!cac_SamAddGroupMember(hnd, mem_ctx, &add)) {
|
---|
188 | printerr("Could not add user to group.", hnd->status);
|
---|
189 | }
|
---|
190 |
|
---|
191 | cac_SamClose(hnd, mem_ctx, og.out.group_hnd);
|
---|
192 | }
|
---|
193 |
|
---|
194 | void remove_user_from_group(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, CacUserInfo *info, POLICY_HND *dom_hnd) {
|
---|
195 | int rid_type = 0;
|
---|
196 |
|
---|
197 | char *tmp = NULL;
|
---|
198 |
|
---|
199 | struct SamOpenGroup og;
|
---|
200 | struct SamRemoveGroupMember del;
|
---|
201 |
|
---|
202 | ZERO_STRUCT(og);
|
---|
203 | ZERO_STRUCT(del);
|
---|
204 |
|
---|
205 | printf("Group RID or Name:");
|
---|
206 |
|
---|
207 | og.in.dom_hnd = dom_hnd;
|
---|
208 | og.in.access = MAXIMUM_ALLOWED_ACCESS;
|
---|
209 | rid_type = rid_or_name(hnd, mem_ctx, dom_hnd, &og.in.rid, &tmp);
|
---|
210 |
|
---|
211 | if(!cac_SamOpenGroup(hnd, mem_ctx, &og)) {
|
---|
212 | printerr("Could not open group.", hnd->status);
|
---|
213 | return;
|
---|
214 | }
|
---|
215 |
|
---|
216 | del.in.group_hnd = og.out.group_hnd;
|
---|
217 | del.in.rid = info->rid;
|
---|
218 |
|
---|
219 | if(!cac_SamRemoveGroupMember(hnd, mem_ctx, &del)) {
|
---|
220 | printerr("Could not add user to group.", hnd->status);
|
---|
221 | }
|
---|
222 |
|
---|
223 | cac_SamClose(hnd, mem_ctx, og.out.group_hnd);
|
---|
224 | }
|
---|
225 |
|
---|
226 | void user_menu(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *dom_hnd, POLICY_HND *user_hnd) {
|
---|
227 | fstring in;
|
---|
228 |
|
---|
229 | struct SamGetUserInfo getinfo;
|
---|
230 | struct SamSetPassword setpass;
|
---|
231 | struct SamGetGroupsForUser groups;
|
---|
232 | struct SamGetNamesFromRids gnfr;
|
---|
233 |
|
---|
234 | CacUserInfo *info = NULL;
|
---|
235 |
|
---|
236 | if(!hnd || !mem_ctx || !user_hnd) {
|
---|
237 | printf("Must open user.\n");
|
---|
238 | return;
|
---|
239 | }
|
---|
240 |
|
---|
241 | /*get the userinfo and print it out*/
|
---|
242 | ZERO_STRUCT(getinfo);
|
---|
243 | getinfo.in.user_hnd = user_hnd;
|
---|
244 |
|
---|
245 | if(!cac_SamGetUserInfo(hnd, mem_ctx, &getinfo)) {
|
---|
246 | printerr("Could not get info.", hnd->status);
|
---|
247 | info = NULL;
|
---|
248 | }
|
---|
249 | else {
|
---|
250 | info = getinfo.out.info;
|
---|
251 | print_user_info(info);
|
---|
252 | }
|
---|
253 |
|
---|
254 | /*now deal with the menu*/
|
---|
255 | in[0] = '\0';
|
---|
256 | while(in[0] != 'b' && in[0] != 'B' && in[0] != 'q' && in[0] != 'Q') {
|
---|
257 | printf("\n");
|
---|
258 | printf("[s] Set Password\n");
|
---|
259 |
|
---|
260 | if(info && (info->acb_mask & ACB_DISABLED))
|
---|
261 | printf("[e] Enable User\n");
|
---|
262 | else if(info)
|
---|
263 | printf("[d] Disable User\n");
|
---|
264 |
|
---|
265 | printf("[v] View User Info\n");
|
---|
266 | printf("[m] Modify User Info\n");
|
---|
267 | printf("[x] Delete User\n\n");
|
---|
268 |
|
---|
269 | printf("[g] List Group Membership\n");
|
---|
270 | printf("[a] Add User To Group\n");
|
---|
271 | printf("[l] List Domain Groups\n");
|
---|
272 | printf("[r] Remove User From Group\n\n");
|
---|
273 |
|
---|
274 | printf("[b] Back\n\n");
|
---|
275 |
|
---|
276 | printf("Command: ");
|
---|
277 | mgr_getline(in);
|
---|
278 |
|
---|
279 | printf("\n");
|
---|
280 |
|
---|
281 | switch(in[0]) {
|
---|
282 | case 'g': /*list group membership*/
|
---|
283 | case 'G':
|
---|
284 | ZERO_STRUCT(groups);
|
---|
285 | groups.in.user_hnd = user_hnd;
|
---|
286 |
|
---|
287 | if(!cac_SamGetGroupsForUser(hnd, mem_ctx, &groups)) {
|
---|
288 | printerr("Could not get groups.", hnd->status);
|
---|
289 | break;
|
---|
290 | }
|
---|
291 |
|
---|
292 | ZERO_STRUCT(gnfr);
|
---|
293 | gnfr.in.dom_hnd = dom_hnd;
|
---|
294 | gnfr.in.rids = groups.out.rids;
|
---|
295 | gnfr.in.num_rids = groups.out.num_groups;
|
---|
296 |
|
---|
297 | if(!cac_SamGetNamesFromRids(hnd, mem_ctx, &gnfr)) {
|
---|
298 | printerr("Could not map RIDs to names.", hnd->status);
|
---|
299 | break;
|
---|
300 | }
|
---|
301 |
|
---|
302 | print_lookup_records(gnfr.out.map, gnfr.out.num_names);
|
---|
303 |
|
---|
304 | break;
|
---|
305 | case 's': /*reset password*/
|
---|
306 | case 'S':
|
---|
307 | ZERO_STRUCT(setpass);
|
---|
308 | setpass.in.user_hnd = user_hnd;
|
---|
309 | setpass.in.password = get_new_password(mem_ctx);
|
---|
310 |
|
---|
311 | if(!setpass.in.password) {
|
---|
312 | printf("Out of memory.\n");
|
---|
313 | break;
|
---|
314 | }
|
---|
315 |
|
---|
316 | if(!cac_SamSetPassword(hnd, mem_ctx, &setpass)) {
|
---|
317 | printerr("Could not set password.", hnd->status);
|
---|
318 | }
|
---|
319 | else {
|
---|
320 | printf("Reset password.\n");
|
---|
321 | }
|
---|
322 | break;
|
---|
323 |
|
---|
324 | case 'e': /*enable user*/
|
---|
325 | case 'E':
|
---|
326 | if(info && !(info->acb_mask & ACB_DISABLED))
|
---|
327 | break;
|
---|
328 |
|
---|
329 | if(!cac_SamEnableUser(hnd, mem_ctx, user_hnd)) {
|
---|
330 | printerr("Could not enable user.", hnd->status);
|
---|
331 | }
|
---|
332 | else {
|
---|
333 | printf("Enabled User.\n");
|
---|
334 | /*toggle the disabled ACB bit in our local copy of the info*/
|
---|
335 | info->acb_mask ^= ACB_DISABLED;
|
---|
336 | }
|
---|
337 | break;
|
---|
338 |
|
---|
339 | case 'd': /*disable user*/
|
---|
340 | case 'D':
|
---|
341 | if(info && (info->acb_mask & ACB_DISABLED))
|
---|
342 | break;
|
---|
343 |
|
---|
344 | if(!cac_SamDisableUser(hnd, mem_ctx, user_hnd)) {
|
---|
345 | printerr("Could not disable user.", hnd->status);
|
---|
346 | }
|
---|
347 | else {
|
---|
348 | printf("Disabled User.\n");
|
---|
349 | /*toggle the disabled ACB bit in our local copy of the info*/
|
---|
350 | info->acb_mask ^= ACB_DISABLED;
|
---|
351 | }
|
---|
352 | break;
|
---|
353 |
|
---|
354 | case 'v': /*view user info*/
|
---|
355 | case 'V':
|
---|
356 | ZERO_STRUCT(getinfo);
|
---|
357 | getinfo.in.user_hnd = user_hnd;
|
---|
358 |
|
---|
359 | if(!cac_SamGetUserInfo(hnd, mem_ctx, &getinfo)) {
|
---|
360 | printerr("Could not get info.", hnd->status);
|
---|
361 | info = NULL;
|
---|
362 | }
|
---|
363 | else {
|
---|
364 | info = getinfo.out.info;
|
---|
365 | print_user_info(info);
|
---|
366 | }
|
---|
367 |
|
---|
368 | break;
|
---|
369 |
|
---|
370 | case 'm': /*modify user info*/
|
---|
371 | case 'M':
|
---|
372 | info = modify_user_info(hnd, mem_ctx, user_hnd);
|
---|
373 |
|
---|
374 | if(info)
|
---|
375 | printf("Updated user info.\n");
|
---|
376 | break;
|
---|
377 |
|
---|
378 | case 'l': /*list domain groups*/
|
---|
379 | case 'L':
|
---|
380 | list_groups(hnd, mem_ctx, dom_hnd);
|
---|
381 | break;
|
---|
382 |
|
---|
383 | case 'a': /*add user to group*/
|
---|
384 | case 'A':
|
---|
385 | add_user_to_group(hnd, mem_ctx, info, dom_hnd);
|
---|
386 | break;
|
---|
387 |
|
---|
388 | case 'r': /*remove user from group*/
|
---|
389 | case 'R':
|
---|
390 | remove_user_from_group(hnd, mem_ctx, info, dom_hnd);
|
---|
391 | break;
|
---|
392 |
|
---|
393 | case 'x': /*delete user*/
|
---|
394 | case 'X':
|
---|
395 | if(!cac_SamDeleteUser(hnd, mem_ctx, user_hnd))
|
---|
396 | printerr("Could not delete user.", hnd->status);
|
---|
397 |
|
---|
398 | /*we want to go back to the main menu*/
|
---|
399 | in[0] = 'b';
|
---|
400 | break;
|
---|
401 |
|
---|
402 | case 'b': /*back*/
|
---|
403 | case 'B':
|
---|
404 | case 'q':
|
---|
405 | case 'Q':
|
---|
406 | /*do nothing*/
|
---|
407 | break;
|
---|
408 |
|
---|
409 | default:
|
---|
410 | printf("Invalid command.\n");
|
---|
411 | }
|
---|
412 | }
|
---|
413 |
|
---|
414 | /*close the user before returning*/
|
---|
415 | cac_SamClose(hnd, mem_ctx, user_hnd);
|
---|
416 | }
|
---|