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 23void 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 66CacUserInfo *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 162void 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 194void 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 226void 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} 417