diff options
Diffstat (limited to 'source3/utils')
-rw-r--r-- | source3/utils/editreg.c | 1373 | ||||
-rw-r--r-- | source3/utils/net.c | 79 | ||||
-rw-r--r-- | source3/utils/net_cache.c | 56 | ||||
-rw-r--r-- | source3/utils/ntlm_auth.c | 429 | ||||
-rw-r--r-- | source3/utils/pdbedit.c | 5 | ||||
-rw-r--r-- | source3/utils/profiles.c | 729 |
6 files changed, 19 insertions, 2652 deletions
diff --git a/source3/utils/editreg.c b/source3/utils/editreg.c deleted file mode 100644 index 944da3a9fa..0000000000 --- a/source3/utils/editreg.c +++ /dev/null @@ -1,1373 +0,0 @@ -/* - Samba Unix/Linux SMB client utility editreg.c - Copyright (C) 2002 Richard Sharpe, rsharpe@richardsharpe.com - - 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; either version 2 of the License, or - (at your option) any later version. - - 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. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -/************************************************************************* - - A utility to edit a Windows NT/2K etc registry file. - - Many of the ideas in here come from other people and software. - I first looked in Wine in misc/registry.c and was also influenced by - http://www.wednesday.demon.co.uk/dosreg.html - - Which seems to contain comments from someone else. I reproduce them here - incase the site above disappears. It actually comes from - http://home.eunet.no/~pnordahl/ntpasswd/WinReg.txt. - - The goal here is to read the registry into memory, manipulate it, and then - write it out if it was changed by any actions of the user. - -The windows NT registry has 2 different blocks, where one can occur many -times... - -the "regf"-Block -================ - -"regf" is obviosly the abbreviation for "Registry file". "regf" is the -signature of the header-block which is always 4kb in size, although only -the first 64 bytes seem to be used and a checksum is calculated over -the first 0x200 bytes only! - -Offset Size Contents -0x00000000 D-Word ID: ASCII-"regf" = 0x66676572 -0x00000004 D-Word ???? //see struct REGF -0x00000008 D-Word ???? Always the same value as at 0x00000004 -0x0000000C Q-Word last modify date in WinNT date-format -0x00000014 D-Word 1 -0x00000018 D-Word 3 -0x0000001C D-Word 0 -0x00000020 D-Word 1 -0x00000024 D-Word Offset of 1st key record -0x00000028 D-Word Size of the data-blocks (Filesize-4kb) -0x0000002C D-Word 1 -0x000001FC D-Word Sum of all D-Words from 0x00000000 to -0x000001FB //XOR of all words. Nigel - -I have analyzed more registry files (from multiple machines running -NT 4.0 german version) and could not find an explanation for the values -marked with ???? the rest of the first 4kb page is not important... - -the "hbin"-Block -================ -I don't know what "hbin" stands for, but this block is always a multiple -of 4kb in size. - -Inside these hbin-blocks the different records are placed. The memory- -management looks like a C-compiler heap management to me... - -hbin-Header -=========== -Offset Size Contents -0x0000 D-Word ID: ASCII-"hbin" = 0x6E696268 -0x0004 D-Word Offset from the 1st hbin-Block -0x0008 D-Word Offset to the next hbin-Block -0x001C D-Word Block-size - -The values in 0x0008 and 0x001C should be the same, so I don't know -if they are correct or swapped... - -From offset 0x0020 inside a hbin-block data is stored with the following -format: - -Offset Size Contents -0x0000 D-Word Data-block size //this size must be a -multiple of 8. Nigel -0x0004 ???? Data - -If the size field is negative (bit 31 set), the corresponding block -is free and has a size of -blocksize! - -That does not seem to be true. All block lengths seem to be negative! (Richard Sharpe) - -The data is stored as one record per block. Block size is a multiple -of 4 and the last block reaches the next hbin-block, leaving no room. - -Records in the hbin-blocks -========================== - -nk-Record - - The nk-record can be treated as a kombination of tree-record and - key-record of the win 95 registry. - -lf-Record - - The lf-record is the counterpart to the RGKN-record (the - hash-function) - -vk-Record - - The vk-record consists information to a single value. - -sk-Record - - sk (? Security Key ?) is the ACL of the registry. - -Value-Lists - - The value-lists contain information about which values are inside a - sub-key and don't have a header. - -Datas - - The datas of the registry are (like the value-list) stored without a - header. - -All offset-values are relative to the first hbin-block and point to the -block-size field of the record-entry. to get the file offset, you have to add -the header size (4kb) and the size field (4 bytes)... - -the nk-Record -============= -Offset Size Contents -0x0000 Word ID: ASCII-"nk" = 0x6B6E -0x0002 Word for the root-key: 0x2C, otherwise 0x20 //key symbolic links 0x10. Nigel -0x0004 Q-Word write-date/time in windows nt notation -0x0010 D-Word Offset of Owner/Parent key -0x0014 D-Word number of sub-Keys -0x001C D-Word Offset of the sub-key lf-Records -0x0024 D-Word number of values -0x0028 D-Word Offset of the Value-List -0x002C D-Word Offset of the sk-Record - -0x0030 D-Word Offset of the Class-Name //see NK structure for the use of these fields. Nigel -0x0044 D-Word Unused (data-trash) //some kind of run time index. Does not appear to be important. Nigel -0x0048 Word name-length -0x004A Word class-name length -0x004C ???? key-name - -the Value-List -============== -Offset Size Contents -0x0000 D-Word Offset 1st Value -0x0004 D-Word Offset 2nd Value -0x???? D-Word Offset nth Value - -To determine the number of values, you have to look at the owner-nk-record! - -Der vk-Record -============= -Offset Size Contents -0x0000 Word ID: ASCII-"vk" = 0x6B76 -0x0002 Word name length -0x0004 D-Word length of the data //if top bit is set when offset contains data. Nigel -0x0008 D-Word Offset of Data -0x000C D-Word Type of value -0x0010 Word Flag -0x0012 Word Unused (data-trash) -0x0014 ???? Name - -If bit 0 of the flag-word is set, a name is present, otherwise the value has no name (=default) - -If the data-size is lower 5, the data-offset value is used to store the data itself! - -The data-types -============== -Wert Beteutung -0x0001 RegSZ: character string (in UNICODE!) -0x0002 ExpandSZ: string with "%var%" expanding (UNICODE!) -0x0003 RegBin: raw-binary value -0x0004 RegDWord: Dword -0x0007 RegMultiSZ: multiple strings, seperated with 0 - (UNICODE!) - -The "lf"-record -=============== -Offset Size Contents -0x0000 Word ID: ASCII-"lf" = 0x666C -0x0002 Word number of keys -0x0004 ???? Hash-Records - -Hash-Record -=========== -Offset Size Contents -0x0000 D-Word Offset of corresponding "nk"-Record -0x0004 D-Word ASCII: the first 4 characters of the key-name, padded with 0's. Case sensitiv! - -Keep in mind, that the value at 0x0004 is used for checking the data-consistency! If you change the -key-name you have to change the hash-value too! - -//These hashrecords must be sorted low to high within the lf record. Nigel. - -The "sk"-block -============== -(due to the complexity of the SAM-info, not clear jet) -(This is just a security descriptor in the data. R Sharpe.) - - -Offset Size Contents -0x0000 Word ID: ASCII-"sk" = 0x6B73 -0x0002 Word Unused -0x0004 D-Word Offset of previous "sk"-Record -0x0008 D-Word Offset of next "sk"-Record -0x000C D-Word usage-counter -0x0010 D-Word Size of "sk"-record in bytes -???? //standard self -relative security desciptor. Nigel -???? ???? Security and auditing settings... -???? - -The usage counter counts the number of references to this -"sk"-record. You can use one "sk"-record for the entire registry! - -Windows nt date/time format -=========================== -The time-format is a 64-bit integer which is incremented every -0,0000001 seconds by 1 (I don't know how accurate it realy is!) -It starts with 0 at the 1st of january 1601 0:00! All values are -stored in GMT time! The time-zone is important to get the real -time! - -Common values for win95 and win-nt -================================== -Offset values marking an "end of list", are either 0 or -1 (0xFFFFFFFF). -If a value has no name (length=0, flag(bit 0)=0), it is treated as the -"Default" entry... -If a value has no data (length=0), it is displayed as empty. - -simplyfied win-3.?? registry: -============================= - -+-----------+ -| next rec. |---+ +----->+------------+ -| first sub | | | | Usage cnt. | -| name | | +-->+------------+ | | length | -| value | | | | next rec. | | | text |------->+-------+ -+-----------+ | | | name rec. |--+ +------------+ | xxxxx | - +------------+ | | value rec. |-------->+------------+ +-------+ - v | +------------+ | Usage cnt. | -+-----------+ | | length | -| next rec. | | | text |------->+-------+ -| first sub |------+ +------------+ | xxxxx | -| name | +-------+ -| value | -+-----------+ - -Greatly simplyfied structure of the nt-registry: -================================================ - -+---------------------------------------------------------------+ -| | -v | -+---------+ +---------->+-----------+ +----->+---------+ | -| "nk" | | | lf-rec. | | | nk-rec. | | -| ID | | | # of keys | | | parent |---+ -| Date | | | 1st key |--+ | .... | -| parent | | +-----------+ +---------+ -| suk-keys|-----+ -| values |--------------------->+----------+ -| SK-rec. |---------------+ | 1. value |--> +----------+ -| class |--+ | +----------+ | vk-rec. | -+---------+ | | | .... | - v | | data |--> +-------+ - +------------+ | +----------+ | xxxxx | - | Class name | | +-------+ - +------------+ | - v - +---------+ +---------+ - +----->| next sk |--->| Next sk |--+ - | +---| prev sk |<---| prev sk | | - | | | .... | | ... | | - | | +---------+ +---------+ | - | | ^ | - | | | | - | +--------------------+ | - +----------------------------------+ - ---------------------------------------------------------------------------- - -Hope this helps.... (Although it was "fun" for me to uncover this things, - it took me several sleepless nights ;) - - B.D. - -*************************************************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <assert.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <sys/mman.h> -#include <string.h> -#include <fcntl.h> - -static int verbose = 0; - -/* - * These definitions are for the in-memory registry structure. - * It is a tree structure that mimics what you see with tools like regedit - */ - -/* - * DateTime struct for Windows - */ - -typedef struct date_time_s { - unsigned int low, high; -} NTTIME; - -/* - * Definition of a Key. It has a name, classname, date/time last modified, - * sub-keys, values, and a security descriptor - */ - -#define REG_ROOT_KEY 1 -#define REG_SUB_KEY 2 -#define REG_SYM_LINK 3 - -typedef struct reg_key_s { - char *name; /* Name of the key */ - char *class_name; - int type; /* One of REG_ROOT_KEY or REG_SUB_KEY */ - NTTIME last_mod; /* Time last modified */ - struct reg_key_s *owner; - struct key_list_s *sub_keys; - struct val_list_s *values; - struct key_sec_desc_s *security; -} REG_KEY; - -/* - * The KEY_LIST struct lists sub-keys. - */ - -typedef struct key_list_s { - int key_count; - REG_KEY *keys[1]; -} KEY_LIST; - -typedef struct val_key_s { - char *name; - int has_name; - int data_type; - int data_len; - void *data_blk; /* Might want a separate block */ -} VAL_KEY; - -typedef struct val_list_s { - int val_count; - VAL_KEY *vals[1]; -} VAL_LIST; - -#ifndef MAXSUBAUTHS -#define MAXSUBAUTHS 15 -#endif - -typedef struct dom_sid_s { - unsigned char ver, auths; - unsigned char auth[6]; - unsigned int sub_auths[MAXSUBAUTHS]; -} DOM_SID; - -typedef struct ace_struct_s { - unsigned char type, flags; - unsigned int perms; /* Perhaps a better def is in order */ - DOM_SID trustee; -} ACE; - -typedef struct acl_struct_s { - unsigned short rev, refcnt; - unsigned short num_aces; - ACE *aces[1]; -} ACL; - -typedef struct sec_desc_s { - unsigned int rev, type; - DOM_SID *owner, *group; - ACL *sacl, *dacl; -} SEC_DESC; - -typedef struct key_sec_desc_s { - struct key_sec_desc_s *prev, *next; - int ref_cnt; - SEC_DESC *sec_desc; -} KEY_SEC_DESC; - - -/* - * An API for accessing/creating/destroying items above - */ - -/* - * Iterate over the keys, depth first, calling a function for each key - * and indicating if it is terminal or non-terminal and if it has values. - * - * In addition, for each value in the list, call a value list function - */ - -/* - * There should eventually be one to deal with security keys as well - */ - -typedef int (*key_print_f)(char *path, char *key_name, char *class_name, - int root, int terminal, int values); - -typedef int (*val_print_f)(char *path, char *val_name, int val_type, - int data_len, void *data_blk, int terminal, - int first, int last); - -typedef struct regf_struct_s REGF; - -int nt_key_iterator(REGF *regf, REG_KEY *key_tree, int bf, char *path, - key_print_f key_print, val_print_f val_print); - -int nt_val_list_iterator(REGF *regf, VAL_LIST *val_list, int bf, char *path, - int terminal, val_print_f val_print) -{ - int i; - - if (!val_list) return 1; - - if (!val_print) return 1; - - for (i=0; i<val_list->val_count; i++) { - if (!val_print(path, val_list->vals[i]->name, val_list->vals[i]->data_type, - val_list->vals[i]->data_len, val_list->vals[i]->data_blk, - terminal, - (i == 0), - (i == val_list->val_count))) { - - return 0; - - } - } - - return 1; -} - -int nt_key_list_iterator(REGF *regf, KEY_LIST *key_list, int bf, char *path, - key_print_f key_print, val_print_f val_print) -{ - int i; - - if (!key_list) return 1; - - for (i=0; i< key_list->key_count; i++) { - if (!nt_key_iterator(regf, key_list->keys[i], bf, path, key_print, - val_print)) { - return 0; - } - } - return 1; -} - -int nt_key_iterator(REGF *regf, REG_KEY *key_tree, int bf, char *path, - key_print_f key_print, val_print_f val_print) -{ - int path_len = strlen(path); - char *new_path; - - if (!regf || !key_tree) - return -1; - - /* List the key first, then the values, then the sub-keys */ - - if (key_print) { - - if (!(*key_print)(path, key_tree->name, - key_tree->class_name, - (key_tree->type == REG_ROOT_KEY), - (key_tree->sub_keys == NULL), - (key_tree->values?(key_tree->values->val_count):0))) - return 0; - } - - new_path = (char *)malloc(path_len + 1 + strlen(key_tree->name) + 1); - if (!new_path) return 0; /* Errors? */ - new_path[0] = '\0'; - strcat(new_path, path); - strcat(new_path, "\\"); - strcat(new_path, key_tree->name); - - /* - * Now, iterate through the values in the val_list - */ - - if (key_tree->values && - !nt_val_list_iterator(regf, key_tree->values, bf, new_path, - (key_tree->values!=NULL), - val_print)) { - - free(new_path); - return 0; - } - - /* - * Now, iterate through the keys in the key list - */ - - if (key_tree->sub_keys && - !nt_key_list_iterator(regf, key_tree->sub_keys, bf, new_path, key_print, - val_print)) { - free(new_path); - return 0; - } - - free(new_path); - return 1; -} - -/* Make, delete keys */ - -int nt_delete_val_list(VAL_LIST *vl) -{ - - return 1; -} - -int nt_delete_reg_key(REG_KEY *key) -{ - - return 1; -} - -/* - * Create/delete key lists and add delete keys to/from a list, count the keys - */ - - -/* - * Create/delete value lists, add/delete values, count them - */ - - -/* - * Create/delete security descriptors, add/delete SIDS, count SIDS, etc. - * We reference count the security descriptors. Any new reference increments - * the ref count. If we modify an SD, we copy the old one, dec the ref count - * and make the change. We also want to be able to check for equality so - * we can reduce the number of SDs in use. - */ - - -/* - * Load and unload a registry file. - * - * Load, loads it into memory as a tree, while unload sealizes/flattens it - */ - -/* - * Get the starting record for NT Registry file - */ - -/* A map of sk offsets in the regf to KEY_SEC_DESCs for quick lookup etc */ -typedef struct sk_map_s { - int sk_off; - KEY_SEC_DESC *key_sec_desc; -} SK_MAP; - -/* - * Where we keep all the regf stuff for one registry. - * This is the structure that we use to tie the in memory tree etc - * together. By keeping separate structs, we can operate on different - * registries at the same time. - * Currently, the SK_MAP is an array of mapping structure. - * Since we only need this on input and output, we fill in the structure - * as we go on input. On output, we know how many SK items we have, so - * we can allocate the structure as we need to. - * If you add stuff here that is dynamically allocated, add the - * appropriate free statements below. - */ - -#define REGF_REGTYPE_NONE 0 -#define REGF_REGTYPE_NT 1 -#define REGF_REGTYPE_W9X 2 - -#define TTTONTTIME(r, t1, t2) (r)->last_mod_time.low = (t1); \ - (r)->last_mod_time.high = (t2); - -#define REGF_HDR_BLKSIZ 0x1000 - -struct regf_struct_s { - int reg_type; - char *regfile_name, *outfile_name; - int fd; - struct stat sbuf; - char *base; - int modified; - NTTIME last_mod_time; - REG_KEY *root; /* Root of the tree for this file */ - int sk_count, sk_map_size; - SK_MAP **sk_map; -}; - -/* - * Structures for dealing with the on-disk format of the registry - */ - -#define IVAL(buf) ((unsigned int) \ - (unsigned int)*((unsigned char *)(buf)+3)<<24| \ - (unsigned int)*((unsigned char *)(buf)+2)<<16| \ - (unsigned int)*((unsigned char *)(buf)+1)<<8| \ - (unsigned int)*((unsigned char *)(buf)+0)) - -#define SVAL(buf) ((unsigned short) \ - (unsigned short)*((unsigned char *)(buf)+1)<<8| \ - (unsigned short)*((unsigned char *)(buf)+0)) - -#define OFF(f) ((f) + REGF_HDR_BLKSIZ + 4) -#define LOCN(base, f) ((base) + OFF(f)) - -/* - * All of the structures below actually have a four-byte lenght before them - * which always seems to be negative. The following macro retrieves that - * size as an integer - */ - -#define BLK_SIZE(b) ((int)*(int *)(((int *)b)-1)) - -typedef unsigned int DWORD; -typedef unsigned short WORD; - -#define REG_REGF_ID 0x66676572 - -typedef struct regf_block { - DWORD REGF_ID; /* regf */ - DWORD uk1; - DWORD uk2; - DWORD tim1, tim2; - DWORD uk3; /* 1 */ - DWORD uk4; /* 3 */ - DWORD uk5; /* 0 */ - DWORD uk6; /* 1 */ - DWORD first_key; /* offset */ - unsigned int dblk_size; - DWORD uk7[116]; /* 1 */ - DWORD chksum; -} REGF_HDR; - -typedef struct hbin_sub_struct { - DWORD dblocksize; - char data[1]; -} HBIN_SUB_HDR; - -#define REG_HBIN_ID 0x6E696268 - -typedef struct hbin_struct { - DWORD HBIN_ID; /* hbin */ - DWORD next_off; - DWORD prev_off; - DWORD uk1; - DWORD uk2; - DWORD uk3; - DWORD uk4; - DWORD blk_size; - HBIN_SUB_HDR hbin_sub_hdr; -} HBIN_HDR; - -#define REG_NK_ID 0x6B6E - -typedef struct nk_struct { - WORD NK_ID; - WORD type; - DWORD t1, t2; - DWORD uk1; - DWORD own_off; - DWORD subk_num; - DWORD uk2; - DWORD lf_off; - DWORD uk3; - DWORD val_cnt; - DWORD val_off; - DWORD sk_off; - DWORD clsnam_off; - DWORD unk4[4]; - DWORD unk5; - WORD nam_len; - WORD clsnam_len; - char key_nam[1]; /* Actual length determined by nam_len */ -} NK_HDR; - -#define REG_SK_ID 0x6B73 - -typedef struct sk_struct { - WORD SK_ID; - WORD uk1; - DWORD prev_off; - DWORD next_off; - DWORD ref_cnt; - DWORD rec_size; - char sec_desc[1]; -} SK_HDR; - -typedef struct hash_struct { - DWORD nk_off; - char hash[4]; -} HASH_REC; - -#define REG_LF_ID 0x666C - -typedef struct lf_struct { - WORD LF_ID; - WORD key_count; - struct hash_struct hr[1]; /* Array of hash records, depending on key_count */ -} LF_HDR; - -typedef DWORD VL_TYPE[1]; /* Value list is an array of vk rec offsets */ - -#define REG_VK_ID 0x6B76 - -typedef struct vk_struct { - WORD VK_ID; - WORD nam_len; - DWORD dat_len; /* If top-bit set, offset contains the data */ - DWORD dat_off; - DWORD dat_type; - WORD flag; /* =1, has name, else no name (=Default). */ - WORD unk1; - char dat_name[1]; /* Name starts here ... */ -} VK_HDR; - -#define REG_TYPE_REGSZ 1 -#define REG_TYPE_EXPANDSZ 2 -#define REG_TYPE_BIN 3 -#define REG_TYPE_DWORD 4 -#define REG_TYPE_MULTISZ 7 - -typedef struct _val_str { - unsigned int val; - char * str; -} VAL_STR; - -VAL_STR reg_type_names[] = { - { 1, "REG_SZ" }, - { 2, "REG_EXPAND_SZ" }, - { 3, "REG_BIN" }, - { 4, "REG_DWORD" }, - { 7, "REG_MULTI_SZ" }, - { 0, NULL }, -}; - -char *val_to_str(unsigned int val, VAL_STR *val_array) -{ - int i = 0; - - if (!val_array) return NULL; - - while (val_array[i].val && val_array[i].str) { - - if (val_array[i].val == val) return val_array[i].str; - i++; - - } - - return NULL; - -} - -REG_KEY *nt_get_key_tree(REGF *regf, NK_HDR *nk_hdr, int size); - -int nt_set_regf_input_file(REGF *regf, char *filename) -{ - return ((regf->regfile_name = strdup(filename)) != NULL); -} - -int nt_set_regf_output_file(REGF *regf, char *filename) -{ - return ((regf->outfile_name = strdup(filename)) != NULL); -} - -/* Create a regf structure and init it */ - -REGF *nt_create_regf(void) -{ - REGF *tmp = (REGF *)malloc(sizeof(REGF)); - if (!tmp) return tmp; - bzero(tmp, sizeof(REGF)); - return tmp; -} - -/* Free all the bits and pieces ... Assumes regf was malloc'd */ -/* If you add stuff to REGF, add the relevant free bits here */ -int nt_free_regf(REGF *regf) -{ - if (!regf) return 0; - - if (regf->regfile_name) free(regf->regfile_name); - if (regf->outfile_name) free(regf->outfile_name); - - /* Free the mmap'd area */ - - if (regf->base) munmap(regf->base, regf->sbuf.st_size); - regf->base = NULL; - close(regf->fd); /* Ignore the error :-) */ - - nt_delete_reg_key(regf->root); /* Free the tree */ - free(regf->sk_map); - regf->sk_count = regf->sk_map_size = 0; - - free(regf); - - return 1; -} - -/* - * Convert from UniCode to Ascii ... Does not take into account other lang - * Restrict by ascii_max if > 0 - */ -int uni_to_ascii(unsigned char *uni, unsigned char *ascii, int ascii_max, - int uni_max) -{ - int i = 0; - - while (i < ascii_max && !(!uni[i*2] && !uni[i*2+1])) { - if (uni_max > 0 && (i*2) >= uni_max) break; - ascii[i] = uni[i*2]; - i++; - - } - - ascii[i] = '\0'; - - return i; -} - -/* Get the header of the registry. Return a pointer to the structure - * If the mmap'd area has not been allocated, then mmap the input file - */ -REGF_HDR *nt_get_regf_hdr(REGF *regf) -{ - if (!regf) - return NULL; /* What about errors */ - - if (!regf->regfile_name) - return NULL; /* What about errors */ - - if (!regf->base) { /* Try to mmap etc the file */ - - if ((regf->fd = open(regf->regfile_name, O_RDONLY, 0000)) <0) { - return NULL; /* What about errors? */ - } - - if (fstat(regf->fd, ®f->sbuf) < 0) { - return NULL; - } - - regf->base = mmap(0, regf->sbuf.st_size, PROT_READ, MAP_SHARED, regf->fd, 0); - - if ((int)regf->base == 1) { - fprintf(stderr, "Could not mmap file: %s, %s\n", regf->regfile_name, - strerror(errno)); - return NULL; - } - } - - /* - * At this point, regf->base != NULL, and we should be able to read the - * header - */ - - assert(regf->base != NULL); - - return (REGF_HDR *)regf->base; -} - -/* - * Validate a regf header - * For now, do nothing, but we should check the checksum - */ -int valid_regf_hdr(REGF_HDR *regf_hdr) -{ - if (!regf_hdr) return 0; - - return 1; -} - -/* - * Process a VK header and return a value - */ -VAL_KEY *process_vk(REGF *regf, VK_HDR *vk_hdr, int size) -{ - char val_name[1024]; - int nam_len, dat_len, flag, dat_type, dat_off, vk_id; - char *val_type; - VAL_KEY *tmp = NULL; - - if (!vk_hdr) return NULL; - - if ((vk_id = SVAL(&vk_hdr->VK_ID)) != REG_VK_ID) { - fprintf(stderr, "Unrecognized VK header ID: %0X, block: %0X, %s\n", - vk_id, (int)vk_hdr, regf->regfile_name); - return NULL; - } - - nam_len = SVAL(&vk_hdr->nam_len); - val_name[nam_len] = '\0'; - flag = SVAL(&vk_hdr->flag); - dat_type = IVAL(&vk_hdr->dat_type); - dat_len = IVAL(&vk_hdr->dat_len); /* If top bit, offset contains data */ - dat_off = IVAL(&vk_hdr->dat_off); - - tmp = (VAL_KEY *)malloc(sizeof(VAL_KEY)); - if (!tmp) { - goto error; - } - bzero(tmp, sizeof(VAL_KEY)); - tmp->has_name = flag; - tmp->data_type = dat_type; - - if (flag & 0x01) { - strncpy(val_name, vk_hdr->dat_name, nam_len); - tmp->name = strdup(val_name); - if (!tmp->name) { - goto error; - } - } - else - strncpy(val_name, "<No Name>", 10); - - /* - * Allocate space and copy the data as a BLOB - */ - - if (dat_len) { - - char *dtmp = (char *)malloc(dat_len&0x7FFFFFFF); - - if (!dtmp) { - goto error; - } - - tmp->data_blk = dtmp; - - if ((dat_len&0x80000000) == 0) { /* The data is pointed to by the offset */ - char *dat_ptr = LOCN(regf->base, dat_off); - bcopy(dat_ptr, dtmp, dat_len); - } - else { /* The data is in the offset */ - dat_len = dat_len & 0x7FFFFFFF; - bcopy(&dat_off, dtmp, dat_len); - } - - } - - val_type = val_to_str(dat_type, reg_type_names); - - /* - * We need to save the data area as well - */ - - if (verbose) fprintf(stdout, " %s : %s : \n", val_name, val_type); - - return tmp; - - error: - /* XXX: FIXME, free the partially allocated struct */ - return NULL; - -} - -/* - * Process a VL Header and return a list of values - */ -VAL_LIST *process_vl(REGF *regf, VL_TYPE vl, int count, int size) -{ - int i, vk_off; - VK_HDR *vk_hdr; - VAL_LIST *tmp = NULL; - - if (-size < (count+1)*sizeof(int)){ - fprintf(stderr, "Error in VL header format. Size less than space required. %d\n", -size); - return NULL; - } - - tmp = (VAL_LIST *)malloc(sizeof(VAL_LIST) + (count - 1) * sizeof(VAL_KEY *)); - if (!tmp) { - goto error; - } - - for (i=0; i<count; i++) { - vk_off = IVAL(&vl[i]); - vk_hdr = (VK_HDR *)LOCN(regf->base, vk_off); - tmp->vals[i] = process_vk(regf, vk_hdr, BLK_SIZE(vk_hdr)); - if (!tmp->vals[i]){ - goto error; - } - } - - tmp->val_count = count; - - return tmp; - - error: - /* XXX: FIXME, free the partially allocated structure */ - return NULL; -} - -/* - * Process an LF Header and return a list of sub-keys - */ -KEY_LIST *process_lf(REGF *regf, LF_HDR *lf_hdr, int size) -{ - int count, i, nk_off; - unsigned int lf_id; - KEY_LIST *tmp; - - if (!lf_hdr) return NULL; - - if ((lf_id = SVAL(&lf_hdr->LF_ID)) != REG_LF_ID) { - fprintf(stderr, "Unrecognized LF Header format: %0X, Block: %0X, %s.\n", - lf_id, (int)lf_hdr, regf->regfile_name); - return NULL; - } - - assert(size < 0); - - count = SVAL(&lf_hdr->key_count); - - if (count <= 0) return NULL; - - /* Now, we should allocate a KEY_LIST struct and fill it in ... */ - - tmp = (KEY_LIST *)malloc(sizeof(KEY_LIST) + (count - 1) * sizeof(REG_KEY *)); - if (!tmp) { - goto error; - } - - tmp->key_count = count; - - for (i=0; i<count; i++) { - NK_HDR *nk_hdr; - - nk_off = IVAL(&lf_hdr->hr[i].nk_off); - nk_hdr = (NK_HDR *)LOCN(regf->base, nk_off); - tmp->keys[i] = nt_get_key_tree(regf, nk_hdr, BLK_SIZE(nk_hdr)); - if (!tmp->keys[i]) { - goto error; - } - } - - return tmp; - - error: - /* XXX: FIXME, free the partially allocated structure */ - return NULL; -} - -/* - * This routine is passed a NK_HDR pointer and retrieves the entire tree - * from there down. It return a REG_KEY *. - */ -REG_KEY *nt_get_key_tree(REGF *regf, NK_HDR *nk_hdr, int size) -{ - REG_KEY *tmp = NULL; - int name_len, clsname_len, lf_off, val_off, val_count, sk_off; - unsigned int nk_id; - LF_HDR *lf_hdr; - VL_TYPE *vl; - SK_HDR *sk_hdr; - char key_name[1024], cls_name[1024]; - - if (!nk_hdr) return NULL; - - if ((nk_id = SVAL(&nk_hdr->NK_ID)) != REG_NK_ID) { - fprintf(stderr, "Unrecognized NK Header format: %08X, Block: %0X. %s\n", - nk_id, (int)nk_hdr, regf->regfile_name); - return NULL; - } - - assert(size < 0); - - name_len = SVAL(&nk_hdr->nam_len); - clsname_len = SVAL(&nk_hdr->clsnam_len); - - /* - * The value of -size should be ge - * (sizeof(NK_HDR) - 1 + name_len) - * The -1 accounts for the fact that we included the first byte of - * the name in the structure. clsname_len is the length of the thing - * pointed to by clsnam_off - */ - - if (-size < (sizeof(NK_HDR) - 1 + name_len)) { - fprintf(stderr, "Incorrect NK_HDR size: %d, %0X\n", -size, (int)nk_hdr); - fprintf(stderr, "Sizeof NK_HDR: %d, name_len %d, clsname_len %d\n", - sizeof(NK_HDR), name_len, clsname_len); - /*return NULL;*/ - } - - if (verbose) fprintf(stdout, "NK HDR: Name len: %d, class name len: %d\n", - name_len, clsname_len); - - /* Fish out the key name and process the LF list */ - - assert(name_len < sizeof(key_name)); - - /* Allocate the key struct now */ - tmp = (REG_KEY *)malloc(sizeof(REG_KEY)); - if (!tmp) return tmp; - bzero(tmp, sizeof(REG_KEY)); - - tmp->type = (SVAL(&nk_hdr->type)==0x2C?REG_ROOT_KEY:REG_SUB_KEY); - - strncpy(key_name, nk_hdr->key_nam, name_len); - key_name[name_len] = '\0'; - - if (verbose) fprintf(stdout, "Key name: %s\n", key_name); - - tmp->name = strdup(key_name); - if (!tmp->name) { - goto error; - } - - /* - * Fish out the class name, it is in UNICODE, while the key name is - * ASCII :-) - */ - - if (clsname_len) { /* Just print in Ascii for now */ - char *clsnamep; - int clsnam_off; - - clsnam_off = IVAL(&nk_hdr->clsnam_off); - clsnamep = LOCN(regf->base, clsnam_off); - - bzero(cls_name, clsname_len); - uni_to_ascii(clsnamep, cls_name, sizeof(cls_name), clsname_len); - - /* - * I am keeping class name as an ascii string for the moment. - * That means it needs to be converted on output. - * XXX: FIXME - */ - - tmp->class_name = strdup(cls_name); - if (!tmp->class_name) { - goto error; - } - - if (verbose) fprintf(stdout, " Class Name: %s\n", cls_name); - - } - - /* - * If there are any values, process them here - */ - - val_count = IVAL(&nk_hdr->val_cnt); - - if (val_count) { - - val_off = IVAL(&nk_hdr->val_off); - vl = (VL_TYPE *)LOCN(regf->base, val_off); - - tmp->values = process_vl(regf, *vl, val_count, BLK_SIZE(vl)); - if (!tmp->values) { - goto error; - } - - } - - /* - * Also handle the SK header ... - */ - - sk_off = IVAL(&nk_hdr->sk_off); - sk_hdr = (SK_HDR *)LOCN(regf->base, sk_off); - - if (sk_off != -1) { - - /* To be coded */ - - } - - lf_off = IVAL(&nk_hdr->lf_off); - - /* - * No more subkeys if lf_off == -1 - */ - - if (lf_off != -1) { - - lf_hdr = (LF_HDR *)LOCN(regf->base, lf_off); - - tmp->sub_keys = process_lf(regf, lf_hdr, BLK_SIZE(lf_hdr)); - if (!tmp->sub_keys){ - goto error; - } - - } - - return tmp; - - error: - if (tmp) nt_delete_reg_key(tmp); - return NULL; -} - -int nt_load_registry(REGF *regf) -{ - REGF_HDR *regf_hdr; - unsigned int regf_id, hbin_id; - HBIN_HDR *hbin_hdr; - NK_HDR *first_key; - - /* Get the header */ - - if ((regf_hdr = nt_get_regf_hdr(regf)) == NULL) { - return -1; - } - - /* Now process that header and start to read the rest in */ - - if ((regf_id = IVAL(®f_hdr->REGF_ID)) != REG_REGF_ID) { - fprintf(stderr, "Unrecognized NT registry header id: %0X, %s\n", - regf_id, regf->regfile_name); - return -1; - } - - /* - * Validate the header ... - */ - if (!valid_regf_hdr(regf_hdr)) { - fprintf(stderr, "Registry file header does not validate: %s\n", - regf->regfile_name); - return -1; - } - - /* Update the last mod date, and then go get the first NK record and on */ - - TTTONTTIME(regf, IVAL(®f_hdr->tim1), IVAL(®f_hdr->tim2)); - - /* - * The hbin hdr seems to be just uninteresting garbage. Check that - * it is there, but that is all. - */ - - hbin_hdr = (HBIN_HDR *)(regf->base + REGF_HDR_BLKSIZ); - - if ((hbin_id = IVAL(&hbin_hdr->HBIN_ID)) != REG_HBIN_ID) { - fprintf(stderr, "Unrecognized registry hbin hdr ID: %0X, %s\n", - hbin_id, regf->regfile_name); - return -1; - } - - /* - * Get a pointer to the first key from the hreg_hdr - */ - - first_key = (NK_HDR *)LOCN(regf->base, IVAL(®f_hdr->first_key)); - - /* - * Now, get the registry tree by processing that NK recursively - */ - - regf->root = nt_get_key_tree(regf, first_key, BLK_SIZE(first_key)); - - assert(regf->root != NULL); - - return 1; -} - -/* - * Main code from here on ... - */ - -/* - * key print function here ... - */ - -int print_key(char *path, char *name, char *class_name, int root, - int terminal, int vals) -{ - - if (terminal) fprintf(stdout, "%s\\%s\n", path, name); - - return 1; -} - -/* - * Value print function here ... - */ -int print_val(char *path, char *val_name, int val_type, int data_len, - void *data_blk, int terminal, int first, int last) -{ - if (!terminal && first) - fprintf(stdout, "%s\n", path); - fprintf(stdout, " %s : %s : \n", (val_name?val_name:"<No Name>"), - val_to_str(val_type, reg_type_names)); - return 1; -} - -void usage(void) -{ - fprintf(stderr, "Usage: editreg [-v] [-k] <registryfile>\n"); - fprintf(stderr, "Version: 0.1\n\n"); - fprintf(stderr, "\n\t-v\t sets verbose mode"); -} - -int main(int argc, char *argv[]) -{ - REGF *regf; - extern char *optarg; - extern int optind; - int opt; - - if (argc < 2) { - usage(); - exit(1); - } - - /* - * Now, process the arguments - */ - - while ((opt = getopt(argc, argv, "vk")) != EOF) { - switch (opt) { - case 'v': - verbose++; - break; - - case 'k': - break; - - default: - usage(); - exit(1); - break; - } - } - - if ((regf = nt_create_regf()) == NULL) { - fprintf(stderr, "Could not create registry object: %s\n", strerror(errno)); - exit(2); - } - - if (!nt_set_regf_input_file(regf, argv[optind])) { - fprintf(stderr, "Could not set name of registry file: %s, %s\n", - argv[1], strerror(errno)); - exit(3); - } - - /* Now, open it, and bring it into memory :-) */ - - if (nt_load_registry(regf) < 0) { - fprintf(stderr, "Could not load registry: %s\n", argv[1]); - exit(4); - } - - /* - * At this point, we should have a registry in memory and should be able - * to iterate over it. - */ - - nt_key_iterator(regf, regf->root, 0, "", print_key, print_val); - return 0; -} - diff --git a/source3/utils/net.c b/source3/utils/net.c index ba08feae19..37ceadc372 100644 --- a/source3/utils/net.c +++ b/source3/utils/net.c @@ -389,84 +389,6 @@ static int net_getdomainsid(int argc, const char **argv) return 0; } -static uint32 get_maxrid(void) -{ - SAM_ACCOUNT *pwd = NULL; - uint32 max_rid = 0; - GROUP_MAP *map = NULL; - int num_entries = 0; - int i; - - if (!pdb_setsampwent(False)) { - DEBUG(0, ("load_sampwd_entries: Unable to open passdb.\n")); - return 0; - } - - for (; (NT_STATUS_IS_OK(pdb_init_sam(&pwd))) - && pdb_getsampwent(pwd) == True; pwd=NULL) { - uint32 rid; - - if (!sid_peek_rid(pdb_get_user_sid(pwd), &rid)) { - DEBUG(0, ("can't get RID for user '%s'\n", - pdb_get_username(pwd))); - pdb_free_sam(&pwd); - continue; - } - - if (rid > max_rid) - max_rid = rid; - - DEBUG(1,("%d is user '%s'\n", rid, pdb_get_username(pwd))); - pdb_free_sam(&pwd); - } - - pdb_endsampwent(); - pdb_free_sam(&pwd); - - if (!pdb_enum_group_mapping(SID_NAME_UNKNOWN, &map, &num_entries, - ENUM_ONLY_MAPPED, MAPPING_WITHOUT_PRIV)) - return max_rid; - - for (i = 0; i < num_entries; i++) { - uint32 rid; - - if (!sid_peek_check_rid(get_global_sam_sid(), &map[i].sid, - &rid)) { - DEBUG(3, ("skipping map for group '%s', SID %s\n", - map[i].nt_name, - sid_string_static(&map[i].sid))); - continue; - } - DEBUG(1,("%d is group '%s'\n", rid, map[i].nt_name)); - - if (rid > max_rid) - max_rid = rid; - } - - SAFE_FREE(map); - - return max_rid; -} - -static int net_maxrid(int argc, const char **argv) -{ - uint32 rid; - - if (argc != 0) { - DEBUG(0, ("usage: net initrid\n")); - return 1; - } - - if ((rid = get_maxrid()) == 0) { - DEBUG(0, ("can't get current maximum rid\n")); - return 1; - } - - d_printf("Currently used maximum rid: %d\n", rid); - - return 0; -} - /* main function table */ static struct functable net_func[] = { {"RPC", net_rpc}, @@ -494,7 +416,6 @@ static struct functable net_func[] = { {"GETLOCALSID", net_getlocalsid}, {"SETLOCALSID", net_setlocalsid}, {"GETDOMAINSID", net_getdomainsid}, - {"MAXRID", net_maxrid}, {"HELP", net_help}, {NULL, NULL} diff --git a/source3/utils/net_cache.c b/source3/utils/net_cache.c index 93c4f1aa1d..359c06d1aa 100644 --- a/source3/utils/net_cache.c +++ b/source3/utils/net_cache.c @@ -34,34 +34,15 @@ * (print_cache_entry) and to flush it (delete_cache_entry). * Both of them are defined by first arg of gencache_iterate() routine. */ -static void print_cache_entry(const char* keystr, const char* datastr, - const time_t timeout, void* dptr) +static void print_cache_entry(const char* keystr, const char* datastr, const time_t timeout) { - char* timeout_str; - time_t now_t = time(NULL); - struct tm timeout_tm, *now_tm; - /* localtime returns statically allocated pointer, so timeout_tm - has to be copied somewhere else */ - memcpy(&timeout_tm, localtime(&timeout), sizeof(struct tm)); - now_tm = localtime(&now_t); - - /* form up timeout string depending whether it's today's date or not */ - if (timeout_tm.tm_year != now_tm->tm_year || - timeout_tm.tm_mon != now_tm->tm_mon || - timeout_tm.tm_mday != now_tm->tm_mday) { - - timeout_str = asctime(&timeout_tm); - timeout_str[strlen(timeout_str) - 1] = '\0'; /* remove tailing CR */ - } else - asprintf(&timeout_str, "%.2d:%.2d:%.2d", timeout_tm.tm_hour, - timeout_tm.tm_min, timeout_tm.tm_sec); - - d_printf("Key: %s\t Timeout: %s\t Value: %s %s\n", keystr, - timeout_str, datastr, timeout > now_t ? "": "(expired)"); + char* timeout_str = ctime(&timeout); + timeout_str[strlen(timeout_str) - 1] = '\0'; + d_printf("Key: %s\t\t Value: %s\t\t Timeout: %s %s\n", keystr, datastr, + timeout_str, timeout > time(NULL) ? "": "(expired)"); } -static void delete_cache_entry(const char* keystr, const char* datastr, - const time_t timeout, void* dptr) +static void delete_cache_entry(const char* keystr, const char* datastr, const time_t timeout) { if (!gencache_del(keystr)) d_printf("Couldn't delete entry! key = %s", keystr); @@ -125,7 +106,7 @@ static time_t parse_timeout(const char* timeout_str) /** - * Add an entry to the cache. If it does exist, then set it. + * Add an entry to the cache * * @param argv key, value and timeout are passed in command line * @return 0 on success, otherwise failure @@ -151,12 +132,12 @@ static int net_cache_add(int argc, const char **argv) return -1; } - if (gencache_set(keystr, datastr, timeout)) { + if (gencache_add(keystr, datastr, timeout)) { d_printf("New cache entry stored successfully.\n"); gencache_shutdown(); return 0; - } - + } + d_printf("Entry couldn't be added. Perhaps there's already such a key.\n"); gencache_shutdown(); return -1; @@ -164,8 +145,7 @@ static int net_cache_add(int argc, const char **argv) /** - * Set new value of an existing entry in the cache. Fail If the entry doesn't - * exist. + * Set new value of an existing entry in the cache * * @param argv key being searched and new value and timeout to set in the entry * @return 0 on success, otherwise failure @@ -191,7 +171,7 @@ static int net_cache_set(int argc, const char **argv) return -1; } - if (gencache_set_only(keystr, datastr, timeout)) { + if (gencache_set(keystr, datastr, timeout)) { d_printf("Cache entry set successfully.\n"); gencache_shutdown(); return 0; @@ -221,7 +201,7 @@ static int net_cache_del(int argc, const char **argv) if(gencache_del(keystr)) { d_printf("Entry deleted.\n"); return 0; - } + } d_printf("Couldn't delete specified entry\n"); return -1; @@ -246,9 +226,9 @@ static int net_cache_get(int argc, const char **argv) } if (gencache_get(keystr, &valuestr, &timeout)) { - print_cache_entry(keystr, valuestr, timeout, NULL); + print_cache_entry(keystr, valuestr, timeout); return 0; - } + } d_printf("Failed to find entry\n"); return -1; @@ -271,7 +251,7 @@ static int net_cache_search(int argc, const char **argv) } pattern = argv[0]; - gencache_iterate(print_cache_entry, NULL, pattern); + gencache_iterate(print_cache_entry, pattern); return 0; } @@ -285,7 +265,7 @@ static int net_cache_search(int argc, const char **argv) static int net_cache_list(int argc, const char **argv) { const char* pattern = "*"; - gencache_iterate(print_cache_entry, NULL, pattern); + gencache_iterate(print_cache_entry, pattern); gencache_shutdown(); return 0; } @@ -300,7 +280,7 @@ static int net_cache_list(int argc, const char **argv) static int net_cache_flush(int argc, const char **argv) { const char* pattern = "*"; - gencache_iterate(delete_cache_entry, NULL, pattern); + gencache_iterate(delete_cache_entry, pattern); gencache_shutdown(); return 0; } diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c deleted file mode 100644 index e710a8c0d0..0000000000 --- a/source3/utils/ntlm_auth.c +++ /dev/null @@ -1,429 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind status program. - - Copyright (C) Tim Potter 2000-2002 - Copyright (C) Andrew Bartlett 2002 - Copyright (C) Francesco Chemolli <kinkie@kame.usr.dsi.unimi.it> 2000 - - 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; either version 2 of the License, or - (at your option) any later version. - - 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. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - -#define SQUID_BUFFER_SIZE 2010 - -enum squid_mode { - SQUID_2_5_BASIC, - SQUID_2_4_BASIC -}; - - -extern int winbindd_fd; - -static const char *helper_protocol; -static const char *username; -static const char *domain; -static const char *workstation; -static const char *hex_challenge; -static const char *hex_lm_response; -static const char *hex_nt_response; -static unsigned char *challenge; -static size_t challenge_len; -static unsigned char *lm_response; -static size_t lm_response_len; -static unsigned char *nt_response; -static size_t nt_response_len; - -static char *password; - -static char winbind_separator(void) -{ - struct winbindd_response response; - static BOOL got_sep; - static char sep; - - if (got_sep) - return sep; - - ZERO_STRUCT(response); - - /* Send off request */ - - if (winbindd_request(WINBINDD_INFO, NULL, &response) != - NSS_STATUS_SUCCESS) { - d_printf("could not obtain winbind separator!\n"); - return '\\'; - } - - sep = response.data.info.winbind_separator; - got_sep = True; - - if (!sep) { - d_printf("winbind separator was NULL!\n"); - return '\\'; - } - - return sep; -} - -static const char *get_winbind_domain(void) -{ - struct winbindd_response response; - - static fstring winbind_domain; - - ZERO_STRUCT(response); - - /* Send off request */ - - if (winbindd_request(WINBINDD_DOMAIN_NAME, NULL, &response) != - NSS_STATUS_SUCCESS) { - d_printf("could not obtain winbind domain name!\n"); - return NULL; - } - - fstrcpy(winbind_domain, response.data.domain_name); - - return winbind_domain; - -} - -/* Authenticate a user with a plaintext password */ - -static BOOL check_plaintext_auth(const char *user, const char *pass, BOOL stdout_diagnostics) -{ - struct winbindd_request request; - struct winbindd_response response; - NSS_STATUS result; - - /* Send off request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - fstrcpy(request.data.auth.user, user); - fstrcpy(request.data.auth.pass, pass); - - result = winbindd_request(WINBINDD_PAM_AUTH, &request, &response); - - /* Display response */ - - if (stdout_diagnostics) { - if ((result != NSS_STATUS_SUCCESS) && (response.data.auth.nt_status == 0)) { - d_printf("Reading winbind reply failed! (0x01)\n"); - } - - d_printf("%s (0x%x)\n", - response.data.auth.nt_status_string, - response.data.auth.nt_status); - } else { - if ((result != NSS_STATUS_SUCCESS) && (response.data.auth.nt_status == 0)) { - DEBUG(1, ("Reading winbind reply failed! (0x01)\n")); - } - - DEBUG(3, ("%s (0x%x)\n", - response.data.auth.nt_status_string, - response.data.auth.nt_status)); - } - - return (result == NSS_STATUS_SUCCESS); -} - -static void manage_squid_basic_request(enum squid_mode squid_mode) -{ - char buf[SQUID_BUFFER_SIZE+1]; - int length; - char *c, *user, *pass; - static BOOL err; - - if (x_fgets(buf, sizeof(buf)-1, x_stdin) == NULL) { - DEBUG(1, ("fgets() failed! dying..... errno=%d (%s)\n", errno, - strerror(errno))); - exit(1); /* BIIG buffer */ - } - - c=memchr(buf,'\n',sizeof(buf)-1); - if (c) { - *c = '\0'; - length = c-buf; - } else { - err = 1; - return; - } - if (err) { - DEBUG(2, ("Oversized message\n")); - x_fprintf(x_stderr, "ERR\n"); - err = 0; - return; - } - - DEBUG(10, ("Got '%s' from squid (length: %d).\n",buf,length)); - - if (buf[0] == '\0') { - DEBUG(2, ("Invalid Request\n")); - x_fprintf(x_stderr, "ERR\n"); - return; - } - - user=buf; - - pass=memchr(buf,' ',length); - if (!pass) { - DEBUG(2, ("Password not found. Denying access\n")); - x_fprintf(x_stderr, "ERR\n"); - return; - } - *pass='\0'; - pass++; - - if (squid_mode == SQUID_2_5_BASIC) { - rfc1738_unescape(user); - rfc1738_unescape(pass); - } - - if (check_plaintext_auth(user, pass, False)) { - x_fprintf(x_stdout, "OK\n"); - } else { - x_fprintf(x_stdout, "ERR\n"); - } -} - - -static void squid_basic(enum squid_mode squid_mode) { - /* initialize FDescs */ - x_setbuf(x_stdout, NULL); - x_setbuf(x_stderr, NULL); - while(1) { - manage_squid_basic_request(squid_mode); - } -} - - -/* Authenticate a user with a challenge/response */ - -static BOOL check_auth_crap(void) -{ - struct winbindd_request request; - struct winbindd_response response; - NSS_STATUS result; - /* Send off request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - fstrcpy(request.data.auth_crap.user, username); - - fstrcpy(request.data.auth_crap.domain, domain); - fstrcpy(request.data.auth_crap.workstation, workstation); - - memcpy(request.data.auth_crap.chal, challenge, MIN(challenge_len, 8)); - - memcpy(request.data.auth_crap.lm_resp, lm_response, MIN(lm_response_len, sizeof(request.data.auth_crap.lm_resp))); - - memcpy(request.data.auth_crap.nt_resp, nt_response, MIN(nt_response_len, sizeof(request.data.auth_crap.nt_resp))); - - request.data.auth_crap.lm_resp_len = lm_response_len; - request.data.auth_crap.nt_resp_len = nt_response_len; - - result = winbindd_request(WINBINDD_PAM_AUTH_CRAP, &request, &response); - - /* Display response */ - - if ((result != NSS_STATUS_SUCCESS) && (response.data.auth.nt_status == 0)) { - d_printf("Reading winbind reply failed! (0x01)\n"); - } - - d_printf("%s (0x%x)\n", - response.data.auth.nt_status_string, - response.data.auth.nt_status); - - return result == NSS_STATUS_SUCCESS; -} - -/* Main program */ - -enum { - OPT_USERNAME = 1000, - OPT_DOMAIN, - OPT_WORKSTATION, - OPT_CHALLENGE, - OPT_RESPONSE, - OPT_LM, - OPT_NT, - OPT_PASSWORD -}; - -/************************************************************* - Routine to set hex password characters into an allocated array. -**************************************************************/ - -void hex_encode(const unsigned char *buff_in, size_t len, char **out_hex_buffer) -{ - int i; - char *hex_buffer; - - *out_hex_buffer = smb_xmalloc((len*2)+1); - hex_buffer = *out_hex_buffer; - - for (i = 0; i < len; i++) - slprintf(&hex_buffer[i*2], 3, "%02X", buff_in[i]); -} - -/************************************************************* - Routine to get the 32 hex characters and turn them - into a 16 byte array. -**************************************************************/ - -BOOL hex_decode(const char *hex_buf_in, unsigned char **out_buffer, size_t *size) -{ - int i; - size_t hex_buf_in_len = strlen(hex_buf_in); - unsigned char partial_byte_hex; - unsigned char partial_byte; - char *hexchars = "0123456789ABCDEF"; - char *p; - BOOL high = True; - - if (!hex_buf_in) - return (False); - - *size = (hex_buf_in_len + 1) / 2; - - *out_buffer = smb_xmalloc(*size); - - for (i = 0; i < hex_buf_in_len; i++) { - partial_byte_hex = toupper(hex_buf_in[i]); - - p = strchr(hexchars, partial_byte_hex); - - if (!p) - return (False); - - partial_byte = PTR_DIFF(p, hexchars); - - if (high) { - (*out_buffer)[i / 2] = (partial_byte << 4); - } else { - (*out_buffer)[i / 2] |= partial_byte; - } - high = !high; - } - return (True); -} - - -int main(int argc, const char **argv) -{ - int opt; - - poptContext pc; - struct poptOption long_options[] = { - POPT_AUTOHELP - - { "helper-protocol", 0, POPT_ARG_STRING, &helper_protocol, OPT_DOMAIN, "operate as a stdio-based helper", "helper protocol to use"}, - { "username", 0, POPT_ARG_STRING, &username, OPT_USERNAME, "username"}, - { "domain", 0, POPT_ARG_STRING, &domain, OPT_DOMAIN, "domain name"}, - { "workstation", 0, POPT_ARG_STRING, &domain, OPT_WORKSTATION, "workstation"}, - { "challenge", 0, POPT_ARG_STRING, &hex_challenge, OPT_CHALLENGE, "challenge (HEX encoded)"}, - { "lm-response", 0, POPT_ARG_STRING, &hex_lm_response, OPT_LM, "LM Response to the challenge (HEX encoded)"}, - { "nt-response", 0, POPT_ARG_STRING, &hex_nt_response, OPT_NT, "NT or NTLMv2 Response to the challenge (HEX encoded)"}, - { "password", 0, POPT_ARG_STRING, &password, OPT_PASSWORD, "User's plaintext password"}, - { NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_debug }, - { NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_configfile }, - { 0, 0, 0, 0 } - }; - - /* Samba client initialisation */ - - dbf = x_stderr; - - /* Parse options */ - - pc = poptGetContext("ntlm_auth", argc, argv, long_options, 0); - - /* Parse command line options */ - - if (argc == 1) { - poptPrintHelp(pc, stderr, 0); - return 1; - } - - pc = poptGetContext(NULL, argc, (const char **)argv, long_options, - POPT_CONTEXT_KEEP_FIRST); - - while((opt = poptGetNextOpt(pc)) != -1) { - switch (opt) { - case OPT_CHALLENGE: - if (!hex_decode(hex_challenge, &challenge, &challenge_len)) { - fprintf(stderr, "hex decode of %s failed!\n", hex_challenge); - exit(1); - } - break; - case OPT_LM: - if (!hex_decode(hex_lm_response, &lm_response, &lm_response_len)) { - fprintf(stderr, "hex decode of %s failed!\n", lm_response); - exit(1); - } - break; - case OPT_NT: - if (!hex_decode(hex_lm_response, &lm_response, &lm_response_len)) { - fprintf(stderr, "hex decode of %s failed!\n", lm_response); - exit(1); - } - break; - } - } - - if (helper_protocol) { - if (strcmp(helper_protocol, "squid-2.5-basic")== 0) { - squid_basic(SQUID_2_5_BASIC); - } else if (strcmp(helper_protocol, "squid-2.4-basic")== 0) { - squid_basic(SQUID_2_4_BASIC); - } else { - fprintf(stderr, "unknown helper protocol [%s]\n", helper_protocol); - exit(1); - } - } - - if (domain == NULL) { - domain = get_winbind_domain(); - } - - if (workstation == NULL) { - workstation = ""; - } - - if (challenge) { - if (!check_auth_crap()) { - exit(1); - } - } else if (password) { - fstring user; - snprintf(user, sizeof(user)-1, "%s%c%s", domain, winbind_separator(), username); - if (!check_plaintext_auth(user, password, True)) { - exit(1); - } - } - - /* Exit code */ - - poptFreeContext(pc); - return 0; -} diff --git a/source3/utils/pdbedit.c b/source3/utils/pdbedit.c index 45a63c4b64..6a019e73d7 100644 --- a/source3/utils/pdbedit.c +++ b/source3/utils/pdbedit.c @@ -495,7 +495,7 @@ int main (int argc, char **argv) poptGetArg(pc); /* Drop argv[0], the program name */ if (user_name == NULL) { - user_name = poptGetArg(pc); + user_name = strdup(poptGetArg(pc)); } if (!lp_load(dyn_CONFIGFILE,True,False,False)) { @@ -503,9 +503,6 @@ int main (int argc, char **argv) exit(1); } - if(lp_modules()) - smb_load_modules(lp_modules()); - if (!init_names()) exit(1); diff --git a/source3/utils/profiles.c b/source3/utils/profiles.c deleted file mode 100644 index de18bd0534..0000000000 --- a/source3/utils/profiles.c +++ /dev/null @@ -1,729 +0,0 @@ -/* - Samba Unix/Linux SMB client utility profiles.c - Copyright (C) 2002 Richard Sharpe, rsharpe@richardsharpe.com - - 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; either version 2 of the License, or - (at your option) any later version. - - 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. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -/************************************************************************* - - A utility to report and change SIDs in registry files - - Many of the ideas in here come from other people and software. - I first looked in Wine in misc/registry.c and was also influenced by - http://www.wednesday.demon.co.uk/dosreg.html - - Which seems to contain comments from someone else. I reproduce them here - incase the site above disappears. It actually comes from - http://home.eunet.no/~pnordahl/ntpasswd/WinReg.txt. - -The windows NT registry has 2 different blocks, where one can occure many -times... - -the "regf"-Block -================ - -"regf" is obviosly the abbreviation for "Registry file". "regf" is the -signature of the header-block which is always 4kb in size, although only -the first 64 bytes seem to be used and a checksum is calculated over -the first 0x200 bytes only! - -Offset Size Contents -0x00000000 D-Word ID: ASCII-"regf" = 0x66676572 -0x00000004 D-Word ???? //see struct REGF -0x00000008 D-Word ???? Always the same value as at 0x00000004 -0x0000000C Q-Word last modify date in WinNT date-format -0x00000014 D-Word 1 -0x00000018 D-Word 3 -0x0000001C D-Word 0 -0x00000020 D-Word 1 -0x00000024 D-Word Offset of 1st key record -0x00000028 D-Word Size of the data-blocks (Filesize-4kb) -0x0000002C D-Word 1 -0x000001FC D-Word Sum of all D-Words from 0x00000000 to -0x000001FB //XOR of all words. Nigel - -I have analyzed more registry files (from multiple machines running -NT 4.0 german version) and could not find an explanation for the values -marked with ???? the rest of the first 4kb page is not important... - -the "hbin"-Block -================ -I don't know what "hbin" stands for, but this block is always a multiple -of 4kb in size. - -Inside these hbin-blocks the different records are placed. The memory- -management looks like a C-compiler heap management to me... - -hbin-Header -=========== -Offset Size Contents -0x0000 D-Word ID: ASCII-"hbin" = 0x6E696268 -0x0004 D-Word Offset from the 1st hbin-Block -0x0008 D-Word Offset to the next hbin-Block -0x001C D-Word Block-size - -The values in 0x0008 and 0x001C should be the same, so I don't know -if they are correct or swapped... - -From offset 0x0020 inside a hbin-block data is stored with the following -format: - -Offset Size Contents -0x0000 D-Word Data-block size //this size must be a -multiple of 8. Nigel -0x0004 ???? Data - -If the size field is negative (bit 31 set), the corresponding block -is free and has a size of -blocksize! - -The data is stored as one record per block. Block size is a multiple -of 4 and the last block reaches the next hbin-block, leaving no room. - -Records in the hbin-blocks -========================== - -nk-Record - - The nk-record can be treated as a kombination of tree-record and - key-record of the win 95 registry. - -lf-Record - - The lf-record is the counterpart to the RGKN-record (the - hash-function) - -vk-Record - - The vk-record consists information to a single value. - -sk-Record - - sk (? Security Key ?) is the ACL of the registry. - -Value-Lists - - The value-lists contain information about which values are inside a - sub-key and don't have a header. - -Datas - - The datas of the registry are (like the value-list) stored without a - header. - -All offset-values are relative to the first hbin-block and point to the -block-size field of the record-entry. to get the file offset, you have to add -the header size (4kb) and the size field (4 bytes)... - -the nk-Record -============= -Offset Size Contents -0x0000 Word ID: ASCII-"nk" = 0x6B6E -0x0002 Word for the root-key: 0x2C, otherwise 0x20 //key symbolic links 0x10. Nigel -0x0004 Q-Word write-date/time in windows nt notation -0x0010 D-Word Offset of Owner/Parent key -0x0014 D-Word number of sub-Keys -0x001C D-Word Offset of the sub-key lf-Records -0x0024 D-Word number of values -0x0028 D-Word Offset of the Value-List -0x002C D-Word Offset of the sk-Record - -0x0030 D-Word Offset of the Class-Name //see NK structure for the use of these fields. Nigel -0x0044 D-Word Unused (data-trash) //some kind of run time index. Does not appear to be important. Nigel -0x0048 Word name-length -0x004A Word class-name length -0x004C ???? key-name - -the Value-List -============== -Offset Size Contents -0x0000 D-Word Offset 1st Value -0x0004 D-Word Offset 2nd Value -0x???? D-Word Offset nth Value - -To determine the number of values, you have to look at the owner-nk-record! - -Der vk-Record -============= -Offset Size Contents -0x0000 Word ID: ASCII-"vk" = 0x6B76 -0x0002 Word name length -0x0004 D-Word length of the data //if top bit is set when offset contains data. Nigel -0x0008 D-Word Offset of Data -0x000C D-Word Type of value -0x0010 Word Flag -0x0012 Word Unused (data-trash) -0x0014 ???? Name - -If bit 0 of the flag-word is set, a name is present, otherwise the value has no name (=default) - -If the data-size is lower 5, the data-offset value is used to store the data itself! - -The data-types -============== -Wert Beteutung -0x0001 RegSZ: character string (in UNICODE!) -0x0002 ExpandSZ: string with "%var%" expanding (UNICODE!) -0x0003 RegBin: raw-binary value -0x0004 RegDWord: Dword -0x0007 RegMultiSZ: multiple strings, separated with 0 - (UNICODE!) - -The "lf"-record -=============== -Offset Size Contents -0x0000 Word ID: ASCII-"lf" = 0x666C -0x0002 Word number of keys -0x0004 ???? Hash-Records - -Hash-Record -=========== -Offset Size Contents -0x0000 D-Word Offset of corresponding "nk"-Record -0x0004 D-Word ASCII: the first 4 characters of the key-name, padded with 0's. Case sensitiv! - -Keep in mind, that the value at 0x0004 is used for checking the data-consistency! If you change the -key-name you have to change the hash-value too! - -//These hashrecords must be sorted low to high within the lf record. Nigel. - -The "sk"-block -============== -(due to the complexity of the SAM-info, not clear jet) - -Offset Size Contents -0x0000 Word ID: ASCII-"sk" = 0x6B73 -0x0002 Word Unused -0x0004 D-Word Offset of previous "sk"-Record -0x0008 D-Word Offset of next "sk"-Record -0x000C D-Word usage-counter -0x0010 D-Word Size of "sk"-record in bytes -???? //standard self -relative security desciptor. Nigel -???? ???? Security and auditing settings... -???? - -The usage counter counts the number of references to this -"sk"-record. You can use one "sk"-record for the entire registry! - -Windows nt date/time format -=========================== -The time-format is a 64-bit integer which is incremented every -0,0000001 seconds by 1 (I don't know how accurate it realy is!) -It starts with 0 at the 1st of january 1601 0:00! All values are -stored in GMT time! The time-zone is important to get the real -time! - -Common values for win95 and win-nt -================================== -Offset values marking an "end of list", are either 0 or -1 (0xFFFFFFFF). -If a value has no name (length=0, flag(bit 0)=0), it is treated as the -"Default" entry... -If a value has no data (length=0), it is displayed as empty. - -simplyfied win-3.?? registry: -============================= - -+-----------+ -| next rec. |---+ +----->+------------+ -| first sub | | | | Usage cnt. | -| name | | +-->+------------+ | | length | -| value | | | | next rec. | | | text |------->+-------+ -+-----------+ | | | name rec. |--+ +------------+ | xxxxx | - +------------+ | | value rec. |-------->+------------+ +-------+ - v | +------------+ | Usage cnt. | -+-----------+ | | length | -| next rec. | | | text |------->+-------+ -| first sub |------+ +------------+ | xxxxx | -| name | +-------+ -| value | -+-----------+ - -Greatly simplyfied structure of the nt-registry: -================================================ - -+---------------------------------------------------------------+ -| | -v | -+---------+ +---------->+-----------+ +----->+---------+ | -| "nk" | | | lf-rec. | | | nk-rec. | | -| ID | | | # of keys | | | parent |---+ -| Date | | | 1st key |--+ | .... | -| parent | | +-----------+ +---------+ -| suk-keys|-----+ -| values |--------------------->+----------+ -| SK-rec. |---------------+ | 1. value |--> +----------+ -| class |--+ | +----------+ | vk-rec. | -+---------+ | | | .... | - v | | data |--> +-------+ - +------------+ | +----------+ | xxxxx | - | Class name | | +-------+ - +------------+ | - v - +---------+ +---------+ - +----->| next sk |--->| Next sk |--+ - | +---| prev sk |<---| prev sk | | - | | | .... | | ... | | - | | +---------+ +---------+ | - | | ^ | | - | +----------+ | - +-------------------------------+ - ---------------------------------------------------------------------------- - -Hope this helps.... (Although it was "fun" for me to uncover this things, - it took me several sleepless nights ;) - - B.D. - -*************************************************************************/ -#include "includes.h" -#include <stdio.h> -#include <errno.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <sys/mman.h> - -typedef unsigned int DWORD; -typedef unsigned short WORD; - -#define REG_REGF_ID 0x66676572 - -typedef struct regf_block { - DWORD REGF_ID; /* regf */ - DWORD uk1; - DWORD uk2; - DWORD tim1, tim2; - DWORD uk3; /* 1 */ - DWORD uk4; /* 3 */ - DWORD uk5; /* 0 */ - DWORD uk6; /* 1 */ - DWORD first_key; /* offset */ - unsigned int dblk_size; - DWORD uk7[116]; /* 1 */ - DWORD chksum; -} REGF_HDR; - -typedef struct hbin_sub_struct { - DWORD dblocksize; - char data[1]; -} HBIN_SUB_HDR; - -#define REG_HBIN_ID 0x6E696268 - -typedef struct hbin_struct { - DWORD HBIN_ID; /* hbin */ - DWORD next_off; - DWORD prev_off; - DWORD uk1; - DWORD uk2; - DWORD uk3; - DWORD uk4; - DWORD blk_size; - HBIN_SUB_HDR hbin_sub_hdr; -} HBIN_HDR; - -#define REG_NK_ID 0x6B6E - -typedef struct nk_struct { - WORD NK_ID; - WORD type; - DWORD t1, t2; - DWORD uk1; - DWORD own_off; - DWORD subk_num; - DWORD uk2; - DWORD lf_off; - DWORD uk3; - DWORD val_cnt; - DWORD val_off; - DWORD sk_off; - DWORD clsnam_off; -} NK_HDR; - -#define REG_SK_ID 0x6B73 - -typedef struct sk_struct { - WORD SK_ID; - WORD uk1; - DWORD prev_off; - DWORD next_off; - DWORD ref_cnt; - DWORD rec_size; - char sec_desc[1]; -} SK_HDR; - -typedef struct sec_desc_rec { - WORD rev; - WORD type; - DWORD owner_off; - DWORD group_off; - DWORD sacl_off; - DWORD dacl_off; -} MY_SEC_DESC; - -typedef struct ace_struct { - unsigned char type; - unsigned char flags; - unsigned short length; - unsigned int perms; - DOM_SID trustee; -} ACE; - -typedef struct acl_struct { - WORD rev; - WORD size; - DWORD num_aces; - ACE *aces; /* One or more ACEs */ -} ACL; - -#define OFF(f) (0x1000 + (f) + 4) - -void print_sid(DOM_SID *sid); - -int verbose = 1; -DOM_SID old_sid, new_sid; -int change = 0, new = 0; - -/* Compare two SIDs for equality */ -int my_sid_equal(DOM_SID *s1, DOM_SID *s2) -{ - int sa1, sa2; - - if (s1->sid_rev_num != s2->sid_rev_num) return 0; - - sa1 = s1->num_auths; sa2 = s2->num_auths; - - if (sa1 != sa2) return 0; - - return !bcmp((char *)&s1->id_auth, (char *)&s2->id_auth, - 6 + sa1 * 4); - -} - -/* - * Quick and dirty to read a SID in S-1-5-21-x-y-z-rid format and - * construct a DOM_SID - */ -int get_sid(DOM_SID *sid, char *sid_str) -{ - int i = 0, auth; - char *lstr; - - if (strncmp(sid_str, "S-1-5", 5)) { - fprintf(stderr, "Does not conform to S-1-5...: %s\n", sid_str); - return 0; - } - - /* We only allow strings of form S-1-5... */ - - sid->sid_rev_num = 1; - sid->id_auth[5] = 5; - - lstr = sid_str + 5; - - while (1) { - if (!lstr || !lstr[0] || sscanf(lstr, "-%u", &auth) == 0) { - if (i < 4) { - fprintf(stderr, "Not of form -d-d...: %s, %u\n", lstr, i); - return 0; - } - sid->num_auths=i; - print_sid(sid); - return 1; - } - - SIVAL(&sid->sub_auths[i], 0, auth); - i++; - lstr = strchr(lstr + 1, '-'); - } - - return 1; -} - -/* - * Replace SID1, component by component with SID2 - * Assumes will never be called with unequal length SIDS - * so only touches 21-x-y-z-rid portion - * This routine does not need to deal with endianism as - * long as the incoming SIDs are both in the same (LE) format. - */ -void change_sid(DOM_SID *s1, DOM_SID *s2) -{ - int i; - - for (i=0; i<s1->num_auths; i++) { - s1->sub_auths[i] = s2->sub_auths[i]; - } -} - -void print_sid(DOM_SID *sid) -{ - int i, comps = sid->num_auths; - fprintf(stdout, "S-%u-%u", sid->sid_rev_num, sid->id_auth[5]); - - for (i = 0; i < comps; i++) { - - fprintf(stdout, "-%u", IVAL(&sid->sub_auths[i],0)); - - } - fprintf(stdout, "\n"); -} - -void process_sid(DOM_SID *sid, DOM_SID *o_sid, DOM_SID *n_sid) -{ - int i; - if (my_sid_equal(sid, o_sid)) { - - for (i=0; i<sid->num_auths; i++) { - sid->sub_auths[i] = n_sid->sub_auths[i]; - - } - - } - -} - -void process_acl(ACL *acl, char *prefix) -{ - int ace_cnt, i; - ACE *ace; - - ace_cnt = IVAL(&acl->num_aces, 0); - ace = (ACE *)&acl->aces; - if (verbose) fprintf(stdout, "%sACEs: %u\n", prefix, ace_cnt); - for (i=0; i<ace_cnt; i++) { - if (verbose) fprintf(stdout, "%s Perms: %08X, SID: ", prefix, - IVAL(&ace->perms, 0)); - if (change) - process_sid(&ace->trustee, &old_sid, &new_sid); - print_sid(&ace->trustee); - ace = (ACE *)((char *)ace + SVAL(&ace->length, 0)); - } -} - -void usage(void) -{ - fprintf(stderr, "usage: profiles [-c <OLD-SID> -n <NEW-SID>] <profilefile>\n"); - fprintf(stderr, "Version: %s\n", VERSION); - fprintf(stderr, "\n\t-v\t sets verbose mode"); - fprintf(stderr, "\n\t-c S-1-5-21-z-y-x-oldrid - provides SID to change"); - fprintf(stderr, "\n\t-n S-1-5-21-a-b-c-newrid - provides SID to change to"); - fprintf(stderr, "\n\t\tBoth must be present if the other is."); - fprintf(stderr, "\n\t\tIf neither present, just report the SIDs found\n"); -} - -int main(int argc, char *argv[]) -{ - extern char *optarg; - extern int optind; - int opt; - int fd, start = 0; - char *base; - struct stat sbuf; - REGF_HDR *regf_hdr; - HBIN_HDR *hbin_hdr; - NK_HDR *nk_hdr; - SK_HDR *sk_hdr; - WORD first_sk_off, sk_off; - MY_SEC_DESC *sec_desc; - int *ptr; - - if (argc < 2) { - usage(); - exit(1); - } - - /* - * Now, process the arguments - */ - - while ((opt = getopt(argc, argv, "c:n:v")) != EOF) { - switch (opt) { - case 'c': - change = 1; - if (!get_sid(&old_sid, optarg)) { - fprintf(stderr, "Argument to -c should be a SID in form of S-1-5-...\n"); - usage(); - exit(254); - } - break; - - case 'n': - new = 1; - if (!get_sid(&new_sid, optarg)) { - fprintf(stderr, "Argument to -n should be a SID in form of S-1-5-...\n"); - usage(); - exit(253); - } - - break; - - case 'v': - verbose++; - break; - - default: - usage(); - exit(255); - } - } - - if ((!change & new) || (change & !new)) { - fprintf(stderr, "You must specify both -c and -n if one or the other is set!\n"); - usage(); - exit(252); - } - - fd = open(argv[optind], O_RDWR, 0000); - - if (fd < 0) { - fprintf(stderr, "Could not open %s: %s\n", argv[optind], - strerror(errno)); - exit(2); - } - - if (fstat(fd, &sbuf) < 0) { - fprintf(stderr, "Could not stat file %s, %s\n", argv[optind], - strerror(errno)); - exit(3); - } - - /* - * Now, mmap the file into memory, check the header and start - * dealing with the records. We are interested in the sk record - */ - start = 0; - base = mmap(&start, sbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - - if ((int)base == -1) { - fprintf(stderr, "Could not mmap file: %s, %s\n", argv[optind], - strerror(errno)); - exit(4); - } - - /* - * In what follows, and in places above, in order to work on both LE and - * BE platforms, we have to use the Samba macros to extract SHORT, LONG - * and associated UNSIGNED quantities from the data in the mmap'd file. - * NOTE, however, that we do not need to do anything with memory - * addresses that we construct from pointers in our address space. - * For example, - * - * sec_desc = (MY_SEC_DESC *)&(sk_hdr->sec_desc[0]); - * - * is simply taking the address of a structure we already have the address - * of in our address space, while, the fields within it, will have to - * be accessed with the macros: - * - * owner_sid = (DOM_SID *)(&sk_hdr->sec_desc[0] + - * IVAL(&sec_desc->owner_off, 0)); - * - * Which is pulling out an offset and adding it to an existing pointer. - * - */ - - regf_hdr = (REGF_HDR *)base; - - if (verbose) fprintf(stdout, "Registry file size: %u\n", (unsigned int)sbuf.st_size); - - if (IVAL(®f_hdr->REGF_ID, 0) != REG_REGF_ID) { - fprintf(stderr, "Incorrect Registry file (doesn't have header ID): %s\n", argv[optind]); - exit(5); - } - - if (verbose) fprintf(stdout, "First Key Off: %u, Data Block Size: %u\n", - IVAL(®f_hdr->first_key, 0), - IVAL(®f_hdr->dblk_size, 0)); - - hbin_hdr = (HBIN_HDR *)(base + 0x1000); /* No need for Endian stuff */ - - /* - * This should be the hbin_hdr - */ - - if (IVAL(&hbin_hdr->HBIN_ID, 0) != REG_HBIN_ID) { - fprintf(stderr, "Incorrect hbin hdr: %s\n", argv[optind]); - exit(6); - } - - if (verbose) fprintf(stdout, "Next Off: %u, Prev Off: %u\n", - IVAL(&hbin_hdr->next_off, 0), - IVAL(&hbin_hdr->prev_off, 0)); - - nk_hdr = (NK_HDR *)(base + 0x1000 + IVAL(®f_hdr->first_key, 0) + 4); - - if (SVAL(&nk_hdr->NK_ID, 0) != REG_NK_ID) { - fprintf(stderr, "Incorrect NK Header: %s\n", argv[optind]); - exit(7); - } - - sk_off = first_sk_off = IVAL(&nk_hdr->sk_off, 0); - if (verbose) { - fprintf(stdout, "Type: %0x\n", SVAL(&nk_hdr->type, 0)); - fprintf(stdout, "SK Off : %o\n", (0x1000 + sk_off + 4)); - } - - sk_hdr = (SK_HDR *)(base + 0x1000 + sk_off + 4); - - do { - DOM_SID *owner_sid, *group_sid; - ACL *sacl, *dacl; - if (SVAL(&sk_hdr->SK_ID, 0) != REG_SK_ID) { - fprintf(stderr, "Incorrect SK Header format: %08X\n", - (0x1000 + sk_off + 4)); - exit(8); - } - ptr = (int *)sk_hdr; - if (verbose) fprintf(stdout, "Off: %08X, Refs: %u, Size: %u\n", - sk_off, IVAL(&sk_hdr->ref_cnt, 0), - IVAL(&sk_hdr->rec_size, 0)); - - sec_desc = (MY_SEC_DESC *)&(sk_hdr->sec_desc[0]); - owner_sid = (DOM_SID *)(&sk_hdr->sec_desc[0] + - IVAL(&sec_desc->owner_off, 0)); - group_sid = (DOM_SID *)(&sk_hdr->sec_desc[0] + - IVAL(&sec_desc->group_off, 0)); - sacl = (ACL *)(&sk_hdr->sec_desc[0] + - IVAL(&sec_desc->sacl_off, 0)); - dacl = (ACL *)(&sk_hdr->sec_desc[0] + - IVAL(&sec_desc->dacl_off, 0)); - if (verbose)fprintf(stdout, " Owner SID: "); - if (change) process_sid(owner_sid, &old_sid, &new_sid); - if (verbose) print_sid(owner_sid); - if (verbose) fprintf(stdout, " Group SID: "); - if (change) process_sid(group_sid, &old_sid, &new_sid); - if (verbose) print_sid(group_sid); - fprintf(stdout, " SACL: "); - if (!sec_desc->sacl_off) { /* LE zero == BE zero */ - if (verbose) fprintf(stdout, "NONE\n"); - } - else - process_acl(sacl, " "); - if (verbose) fprintf(stdout, " DACL: "); - if (!sec_desc->dacl_off) { - if (verbose) fprintf(stdout, "NONE\n"); - } - else - process_acl(dacl, " "); - sk_off = IVAL(&sk_hdr->prev_off, 0); - sk_hdr = (SK_HDR *)(base + OFF(IVAL(&sk_hdr->prev_off, 0))); - } while (sk_off != first_sk_off); - - munmap(base, sbuf.st_size); - - close(fd); - return 0; -} |