mirror of
https://github.com/rescatux/chntpw
synced 2026-06-21 14:07:44 +00:00
293 lines
8.3 KiB
C
293 lines
8.3 KiB
C
/*
|
|
* samusrgrp.c - SAM database, add or remove user in a group
|
|
*
|
|
* Command line utility, non-inreractive to add or remove a user to/from
|
|
* a local group in the SAM database, list groups with memberships etc
|
|
*
|
|
* When run as:
|
|
* samusrtogrp - add user to group
|
|
* samusrfromgrp - remove user from a group
|
|
* or as any other name, option of what to do must be specified
|
|
*
|
|
* Changes:
|
|
* 2013 - aug: cleaned up for release, still some debug & strangeness left
|
|
* 2013 - apr-may: add, remove, list working (more or less)
|
|
* 2012 - oct: First version, never released
|
|
*
|
|
*****
|
|
*
|
|
* Copyright (c) 1997-2014 Petter Nordahl-Hagen.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; version 2 of the License.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* See file GPL.txt for the full license.
|
|
*
|
|
*****
|
|
*/
|
|
|
|
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "ntreg.h"
|
|
#include "sam.h"
|
|
|
|
|
|
const char samusrgrp_version[] = "samusrgrp version 0.2 140201, (c) Petter N Hagen";
|
|
|
|
|
|
/* Global verbosity flag */
|
|
int gverbose = 0;
|
|
|
|
/* Array of loaded hives */
|
|
#define MAX_HIVES 10
|
|
struct hive *hive[MAX_HIVES+1];
|
|
int no_hives = 0;
|
|
|
|
int H_SAM = -1;
|
|
|
|
|
|
/* Print machine SID. Put into here since no better place for now */
|
|
|
|
void cmd_machinesid(void)
|
|
{
|
|
struct sid_binary sid;
|
|
char *sidstr;
|
|
|
|
if (sam_get_machine_sid(hive[H_SAM], (char *)&sid)) {
|
|
sidstr = sam_sid_to_string(&sid);
|
|
puts(sidstr);
|
|
FREE(sidstr);
|
|
}
|
|
}
|
|
|
|
/* Get and parse parameters for group changes */
|
|
|
|
int cmd_usrgrp(char *user, char *grp, int what, int human)
|
|
{
|
|
int numgrp;
|
|
int rid = 0;
|
|
char *resolveduser = NULL;
|
|
char *resolvedgroup = NULL;
|
|
char s[200];
|
|
|
|
numgrp = strtol(grp, NULL, 0);
|
|
|
|
if ((H_SAM < 0) || (!user)) return(1);
|
|
|
|
if (*user == '0' && *(user+1) == 'x') sscanf(user,"%i",&rid);
|
|
|
|
if (!rid) { /* Look up username */
|
|
/* Extract the unnamed value out of the username-key, value is RID */
|
|
snprintf(s,180,"\\SAM\\Domains\\Account\\Users\\Names\\%s\\@",user);
|
|
rid = get_dword(hive[H_SAM],0,s, TPF_VK_EXACT|TPF_VK_SHORT);
|
|
if (rid == -1) {
|
|
printf("User <%s> not found\n",user);
|
|
return(1);
|
|
}
|
|
}
|
|
|
|
/* At this point we have a RID, so get the real username it maps to just to show it */
|
|
resolveduser = sam_get_username(hive[H_SAM], rid);
|
|
if (!resolveduser) return(1); /* Fails if RID does not exists */
|
|
|
|
resolvedgroup = sam_get_groupname(hive[H_SAM], numgrp);
|
|
if (!resolvedgroup) return(1); /* Fails if GID does not exists */
|
|
|
|
|
|
if (human) printf("%s user <%s> with RID = %d (0x%0x) %s group <%s> with GID = %d (0x%x)\n",
|
|
(what == 1 ? "Add" : "Remove"),
|
|
resolveduser,
|
|
rid, rid,
|
|
(what == 1 ? "to" : "from"),
|
|
resolvedgroup,
|
|
numgrp, numgrp );
|
|
|
|
FREE(resolveduser);
|
|
FREE(resolvedgroup);
|
|
|
|
switch (what) {
|
|
case 1: return(!sam_add_user_to_grp(hive[H_SAM] ,rid, numgrp)); break;
|
|
case 2: return(!sam_remove_user_from_grp(hive[H_SAM] ,rid, numgrp)); break;
|
|
}
|
|
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void usage(void)
|
|
{
|
|
printf(" [-a|-r] -u <user> -g <groupid> <samhive>\n"
|
|
"Add or remove a (local) user to/from a group\n"
|
|
"Mode:"
|
|
" -a = add user to group\n"
|
|
" -r = remove user from group\n"
|
|
" -l = list groups\n"
|
|
" -L = list groups and also their members\n"
|
|
" -s = Print machine SID\n"
|
|
"Parameters:\n"
|
|
" <user> can be given as a username or a RID in hex with 0x in front\n"
|
|
" <group> is the group number, in hex with 0x in front\n"
|
|
" Example:\n"
|
|
" -a -u theboss -g 0x220 -> add user named 'theboss' group hex 220 (administrators)\n"
|
|
" -a -u 0x3ea -g 0x221 -> add user with RID (hex) 3ea group hex 221 (users)\n"
|
|
" -r -u 0x3ff -g 0x220 -> remove user RID 0x3ff from grp 0x220\n"
|
|
" Usernames with international characters usually fails to be found,\n"
|
|
" please use RID number instead\n"
|
|
" If success, there will be no output, and exit code is 0\n"
|
|
" Also, success if user already in (or not in if -r) the group\n"
|
|
"Options:\n"
|
|
" -H : Human readable output, else parsable\n"
|
|
" -N : No allocate mode, only allow edit of existing values with same size\n"
|
|
" -E : No expand mode, do not expand hive file (safe mode)\n"
|
|
" -t : Debug trace of allocated blocks\n"
|
|
" -v : Some more verbose messages/debug\n"
|
|
"Multi call binary, if program is named:\n"
|
|
" samusrtogrp -- Assume -a mode: Add a user into a group\n"
|
|
" samusrfromgrp -- Assume -r mode: Remove user from a group\n"
|
|
);
|
|
}
|
|
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
|
|
extern int optind;
|
|
extern char* optarg;
|
|
|
|
int what = 0;
|
|
int add = 0;
|
|
int rem = 0;
|
|
int mode = 0;
|
|
int m = 0;
|
|
int list = 0;
|
|
int human = 0;
|
|
int ret, wret, il;
|
|
char *hivename;
|
|
char c;
|
|
char *usr = NULL;
|
|
char *grp = NULL;
|
|
|
|
char *options = "aru:g:vNEthlLHs";
|
|
|
|
if (!strcmp(argv[0],"samusrtogrp")) what = 1;
|
|
if (!strcmp(argv[0],"samusrfromgrp")) what = 2;
|
|
if (!strcmp(argv[0],"samgrplist")) what = 3;
|
|
|
|
while((c=getopt(argc,argv,options)) > 0) {
|
|
switch(c) {
|
|
case 'a': add = 1; m++; break; /* Add user */
|
|
case 'r': rem = 2; m++; break; /* Remove user */
|
|
case 'l': list = 1; m++; break; /* List groups */
|
|
case 'L': list = 2; m++; break; /* List groups + members */
|
|
case 's': list = 3; m++; break; /* Print machine sid */
|
|
case 'u': usr = optarg; break;
|
|
case 'g': grp = optarg; break;
|
|
case 'H': human = 1; break;
|
|
case 'v': mode |= HMODE_VERBOSE; gverbose = 1; break;
|
|
case 'N': mode |= HMODE_NOALLOC; break;
|
|
case 'E': mode |= HMODE_NOEXPAND; break;
|
|
case 't': mode |= HMODE_TRACE; break;
|
|
case 'h': printf("%s\n%s ",samusrgrp_version,argv[0]); usage(); exit(0); break;
|
|
default: printf("%s\n%s ",samusrgrp_version,argv[0]); usage(); exit(1); break;
|
|
}
|
|
}
|
|
|
|
if (m == 0) {
|
|
fprintf(stderr,"%s: ERROR: One of mode -a -r -l -L must be specified\n",argv[0]);
|
|
printf("%s\n%s ",samusrgrp_version,argv[0]);
|
|
usage();
|
|
exit(1);
|
|
}
|
|
|
|
if (m > 1) {
|
|
fprintf(stderr,"%s: ERROR: Please select only one of modes -a -r -l -L\n",argv[0]);
|
|
exit(1);
|
|
}
|
|
|
|
if (!list && (!usr || !grp || !*usr || !*grp) ) {
|
|
fprintf(stderr,"%s: ERROR: Both -u and -g must be specified.\n",argv[0]);
|
|
exit(1);
|
|
}
|
|
|
|
|
|
/* Implicit mode parameter overrides mode based on binary name */
|
|
if (add) what = 1;
|
|
if (rem) what = 2;
|
|
if (list) what = 3;
|
|
|
|
// printf("add = %d, rem = %d, list = %d, what = %d\n",add,rem,list,what);
|
|
|
|
|
|
/* Load hives. Only first SAM hive will be used however */
|
|
|
|
hivename = argv[optind+no_hives];
|
|
if (!hivename || !*hivename) {
|
|
fprintf(stderr,"%s: ERROR: You must specify a SAM registry hive filename.\n",argv[0]);
|
|
exit(1);
|
|
}
|
|
do {
|
|
if (!(hive[no_hives] = openHive(hivename,
|
|
HMODE_RW|mode))) {
|
|
fprintf(stderr,"%s: ERROR: Unable to open/read registry hive, cannot continue\n",argv[0]);
|
|
exit(1);
|
|
}
|
|
switch(hive[no_hives]->type) {
|
|
case HTYPE_SAM: H_SAM = no_hives; break;
|
|
// case HTYPE_SOFTWARE: H_SOF = no_hives; break;
|
|
// case HTYPE_SYSTEM: H_SYS = no_hives; break;
|
|
// case HTYPE_SECURITY: H_SEC = no_hives; break;
|
|
}
|
|
no_hives++;
|
|
hivename = argv[optind+no_hives];
|
|
} while (hivename && *hivename && no_hives < MAX_HIVES);
|
|
|
|
if (H_SAM == -1) {
|
|
fprintf(stderr,"%s: WARNING: Registry hive does not look like SAM!\n"
|
|
"%s: WARNING: Continuing anyway, may lead to strange messages/failures!\n",argv[0],argv[0]);
|
|
H_SAM = 0;
|
|
}
|
|
|
|
|
|
/* Do logic */
|
|
|
|
if (list == 3) {
|
|
cmd_machinesid();
|
|
ret = 0;
|
|
} else {
|
|
if (list) {
|
|
sam_list_groups(hive[H_SAM], list - 1, human);
|
|
ret = 0;
|
|
} else {
|
|
ret = cmd_usrgrp(usr, grp, what, human);
|
|
if (!ret && human) printf("Success!\n");
|
|
}
|
|
}
|
|
|
|
/* write registry hive (if needed) */
|
|
|
|
wret = 0;
|
|
for (il = 0; il < no_hives; il++) {
|
|
wret |= writeHive(hive[il]);
|
|
if (hive[il]->state & HMODE_DIDEXPAND)
|
|
fprintf(stderr," WARNING: Registry file %s was expanded! Experimental! Use at own risk!\n",hive[il]->filename);
|
|
while (no_hives > 0)
|
|
closeHive(hive[--no_hives]);
|
|
}
|
|
|
|
return(ret | wret);
|
|
}
|
|
|