diff options
Diffstat (limited to 'source3/utils')
-rw-r--r-- | source3/utils/editreg.c | 1294 | ||||
-rw-r--r-- | source3/utils/net_ads.c | 13 | ||||
-rw-r--r-- | source3/utils/net_rpc.c | 58 | ||||
-rw-r--r-- | source3/utils/pdbedit.c | 50 | ||||
-rw-r--r-- | source3/utils/smbgroupedit.c | 405 |
5 files changed, 147 insertions, 1673 deletions
diff --git a/source3/utils/editreg.c b/source3/utils/editreg.c index c45959799b..ad4417921c 100644 --- a/source3/utils/editreg.c +++ b/source3/utils/editreg.c @@ -91,16 +91,11 @@ multiple of 8. Nigel 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) +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. -(That also seems incorrect, in that the block size if a multiple of 8. -That is, the block, including the 4 byte header, is always a multiple of -8 bytes. Richard Sharpe.) - Records in the hbin-blocks ========================== @@ -211,7 +206,7 @@ key-name you have to change the hash-value too! The "sk"-block ============== (due to the complexity of the SAM-info, not clear jet) -(This is just a self-relative security descriptor in the data. R Sharpe.) +(This is just a security descriptor in the data. R Sharpe.) Offset Size Contents @@ -315,38 +310,10 @@ Hope this helps.... (Although it was "fun" for me to uncover this things, #define False 0 #define True 1 -#define REG_KEY_LIST_SIZE 10 - -/* - * 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 CVAL(buf) ((unsigned char)*((unsigned char *)(buf))) - -#define SIVAL(buf, val) \ - ((unsigned char)buf[0]=(unsigned char)((val)&0xFF),\ - (unsigned char)buf[1]=(unsigned char)(((val)>>8)&0xFF),\ - (unsigned char)buf[2]=(unsigned char)(((val)>>16)&0xFF),\ - (unsigned char)buf[3]=(unsigned char)((val)>>24)) - -#define SSVAL(buf, val) \ - ((unsigned char)buf[0]=(unsigned char)((val)&0xFF),\ - (unsigned char)buf[1]=(unsigned char)(((val)>>8)&0xFF)) +#define REG_KEY_LIST_SIZE 10; static int verbose = 0; static int print_security = 0; -static int full_print = 0; -static char *def_owner_sid_str = NULL; /* * These definitions are for the in-memory registry structure. @@ -370,8 +337,6 @@ typedef struct date_time_s { #define REG_SUB_KEY 2 #define REG_SYM_LINK 3 -typedef struct key_sec_desc_s KEY_SEC_DESC; - typedef struct reg_key_s { char *name; /* Name of the key */ char *class_name; @@ -380,8 +345,7 @@ typedef struct reg_key_s { struct reg_key_s *owner; struct key_list_s *sub_keys; struct val_list_s *values; - KEY_SEC_DESC *security; - unsigned int offset; /* Offset of the record in the file */ + struct key_sec_desc_s *security; } REG_KEY; /* @@ -404,7 +368,6 @@ typedef struct val_key_s { typedef struct val_list_s { int val_count; - int max_vals; VAL_KEY *vals[1]; } VAL_LIST; @@ -439,19 +402,16 @@ typedef struct sec_desc_s { #define SEC_DESC_NON 0 #define SEC_DESC_RES 1 #define SEC_DESC_OCU 2 -#define SEC_DESC_NBK 3 -typedef struct sk_struct SK_HDR; -struct key_sec_desc_s { + +typedef struct key_sec_desc_s { struct key_sec_desc_s *prev, *next; int ref_cnt; int state; - int offset; - SK_HDR *sk_hdr; /* This means we must keep the registry in memory */ SEC_DESC *sec_desc; -}; +} KEY_SEC_DESC; /* - * All of the structures below actually have a four-byte length before them + * 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 */ @@ -487,8 +447,8 @@ typedef struct hbin_sub_struct { typedef struct hbin_struct { DWORD HBIN_ID; /* hbin */ - DWORD off_from_first; - DWORD off_to_next; + DWORD next_off; + DWORD prev_off; DWORD uk1; DWORD uk2; DWORD uk3; @@ -522,7 +482,7 @@ typedef struct nk_struct { #define REG_SK_ID 0x6B73 -struct sk_struct { +typedef struct sk_struct { WORD SK_ID; WORD uk1; DWORD prev_off; @@ -530,7 +490,7 @@ struct sk_struct { DWORD ref_cnt; DWORD rec_size; char sec_desc[1]; -}; +} SK_HDR; typedef struct ace_struct { unsigned char type; @@ -584,7 +544,6 @@ typedef struct vk_struct { char dat_name[1]; /* Name starts here ... */ } VK_HDR; -#define REG_TYPE_DELETE -1 #define REG_TYPE_NONE 0 #define REG_TYPE_REGSZ 1 #define REG_TYPE_EXPANDSZ 2 @@ -603,26 +562,7 @@ typedef struct sk_map_s { KEY_SEC_DESC *key_sec_desc; } SK_MAP; -/* - * This structure keeps track of the output format of the registry - */ -#define REG_OUTBLK_HDR 1 -#define REG_OUTBLK_HBIN 2 - -typedef struct hbin_blk_s { - int type, size; - struct hbin_blk_s *next; - char *data; /* The data block */ - unsigned int file_offset; /* Offset in file */ - unsigned int free_space; /* Amount of free space in block */ - unsigned int fsp_off; /* Start of free space in block */ - int complete, stored; -} HBIN_BLK; - -/* - * This structure keeps all the registry stuff in one place - */ -typedef struct regf_struct_s { +struct regf_struct_s { int reg_type; char *regfile_name, *outfile_name; int fd; @@ -633,14 +573,9 @@ typedef struct regf_struct_s { REG_KEY *root; /* Root of the tree for this file */ int sk_count, sk_map_size; SK_MAP *sk_map; - char *owner_sid_str; - SEC_DESC *def_sec_desc; - /* - * These next pointers point to the blocks used to contain the - * keys when we are preparing to write them to a file - */ - HBIN_BLK *blk_head, *blk_tail, *free_space; -} REGF; +}; + +typedef struct regf_struct_s REGF; /* * An API for accessing/creating/destroying items above @@ -787,7 +722,7 @@ REG_KEY *nt_find_key_in_list_by_name(KEY_LIST *list, char *key) if (!list || !key || !*key) return NULL; - for (i = 0; i < list->key_count; i++) + for (i = 0; i<= list->key_count; i++) if ((res = nt_find_key_by_name(list->keys[i], key))) return res; @@ -839,7 +774,6 @@ int nt_delete_val_key(VAL_KEY *val_key) { if (val_key) { - if (val_key->name) free(val_key->name); if (val_key->data_blk) free(val_key->data_blk); free(val_key); }; @@ -883,7 +817,6 @@ int nt_delete_key_by_name(REGF *regf, char *name) key = nt_find_key_by_name(regf->root, name); if (key) { - if (key == regf->root) regf->root = NULL; return nt_delete_reg_key(key, True); } @@ -1006,142 +939,6 @@ int nt_delete_reg_key(REG_KEY *key, int delete_name) return 1; } -/* - * Convert a string to a value ... - * FIXME: Error handling and convert this at command parse time ... - */ -void *str_to_val(int type, char *val, int *len) -{ - unsigned int *dwordp = NULL; - - if (!len || !val) return NULL; - - switch (type) { - case REG_TYPE_REGSZ: - *len = strlen(val); - return (void *)val; - - case REG_TYPE_DWORD: - dwordp = (unsigned int *)malloc(sizeof(unsigned int)); - if (!dwordp) return NULL; - /* Allow for ddddd and 0xhhhhh and 0ooooo */ - if (strncmp(val, "0x", 2) == 0 || strncmp(val, "0X", 2) == 0) { - sscanf(&val[2], "%X", dwordp); - } - else if (*val == '0') { - sscanf(&val[1], "%o", dwordp); - } - else { - sscanf(val, "%d", dwordp); - } - *len = sizeof(unsigned int); - return (void *)dwordp; - - /* FIXME: Implement more of these */ - - default: - return NULL; - break; - } - - return NULL; -} - -/* - * Add a value to the key specified ... We have to parse the value some more - * based on the type to get it in the correct internal form - * An empty name will be converted to "<No Name>" before here - * Hmmm, maybe not. has_name is for that - */ -VAL_KEY *nt_add_reg_value(REG_KEY *key, char *name, int type, char *value) -{ - int i; - VAL_KEY *tmp = NULL; - - if (!key || !key->values || !name || !*name) return NULL; - - assert(type != REG_TYPE_DELETE); /* We never process deletes here */ - - for (i = 0; i < key->values->val_count; i++) { - if ((!key->values->vals[i]->has_name && !*name) || - (key->values->vals[i]->has_name && - strcmp(name, key->values->vals[i]->name) == 0)){ /* Change the value */ - free(key->values->vals[i]->data_blk); - key->values->vals[i]->data_blk = str_to_val(type, value, & - key->values->vals[i]->data_len); - return key->values->vals[i]; - } - } - - /* - * If we get here, the name was not found, so insert it - */ - - tmp = (VAL_KEY *)malloc(sizeof(VAL_KEY)); - if (!tmp) goto error; - - bzero(tmp, sizeof(VAL_KEY)); - tmp->name = strdup(name); - tmp->has_name = True; - if (!tmp->name) goto error; - tmp->data_type = type; - tmp->data_blk = str_to_val(type, value, &tmp->data_len); - - /* Now, add to val list */ - - if (key->values->val_count >= key->values->max_vals) { - /* - * Allocate some more space - */ - - if ((key->values = (VAL_LIST *)realloc(key->values, sizeof(VAL_LIST) + - key->values->val_count - 1 + - REG_KEY_LIST_SIZE))) { - key->values->max_vals += REG_KEY_LIST_SIZE; - } - else goto error; - } - - i = key->values->val_count; - key->values->val_count++; - key->values->vals[i] = tmp; - return tmp; - - error: - if (tmp) nt_delete_val_key(tmp); - return NULL; -} - -/* - * Delete a value. We return the value and let the caller deal with it. - */ -VAL_KEY *nt_delete_reg_value(REG_KEY *key, char *name) -{ - int i, j; - - if (!key || !key->values || !name || !*name) return NULL; - - /* FIXME: Allow empty value name */ - for (i = 0; i< key->values->val_count; i++) { - if ((!key->values->vals[i]->has_name && !*name) || - (key->values->vals[i]->has_name && - strcmp(name, key->values->vals[i]->name) == 0)) { - VAL_KEY *val; - - val = key->values->vals[i]; - - /* Shuffle down */ - for (j = i + 1; j < key->values->val_count; j++) - key->values->vals[j - 1] = key->values->vals[j]; - - key->values->val_count--; - - return val; - } - } - return NULL; -} - /* * Add a key to the tree ... We walk down the components matching until * we don't find any. There must be a match on the first component ... @@ -1167,190 +964,32 @@ REG_KEY *nt_create_reg_key1(char *name, REG_KEY *parent) if (!(tmp->name = strdup(name))) goto error; - error: - if (tmp) free(tmp); - return NULL; -} - -/* - * Convert a string of the form S-1-5-x[-y-z-r] to a SID - */ -int string_to_sid(DOM_SID **sid, char *sid_str) -{ - int i = 0, auth; - char *lstr; - - *sid = (DOM_SID *)malloc(sizeof(DOM_SID)); - if (!*sid) return 0; - bzero(*sid, sizeof(DOM_SID)); - - 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)->ver = 1; - (*sid)->auth[5] = 5; - - lstr = sid_str + 5; - - while (1) { - if (!lstr || !lstr[0] || sscanf(lstr, "-%u", &auth) == 0) { - if (i < 1) { - fprintf(stderr, "Not of form -d-d...: %s, %u\n", lstr, i); - return 0; - } - (*sid)->auths=i; - return 1; - } - - (*sid)->sub_auths[i] = auth; - i++; - lstr = strchr(lstr + 1, '-'); - } - - return 1; -} - -/* - * Create an ACE - */ -ACE *nt_create_ace(int type, int flags, unsigned int perms, char *sid) -{ - ACE *ace; - - ace = (ACE *)malloc(sizeof(ACE)); - if (!ace) goto error; - ace->type = type; - ace->flags = flags; - ace->perms = perms; - if (!string_to_sid(&ace->trustee, sid)) - goto error; - return ace; error: - if (ace) nt_delete_ace(ace); - return NULL; -} - -/* - * Create a default ACL - */ -ACL *nt_create_default_acl(REGF *regf) -{ - ACL *acl; - - acl = (ACL *)malloc(sizeof(ACL) + 7*sizeof(ACE *)); - if (!acl) goto error; - - acl->rev = 2; - acl->refcnt = 1; - acl->num_aces = 8; - - acl->aces[0] = nt_create_ace(0x00, 0x0, 0xF003F, regf->owner_sid_str); - if (!acl->aces[0]) goto error; - acl->aces[1] = nt_create_ace(0x00, 0x0, 0xF003F, "S-1-5-18"); - if (!acl->aces[1]) goto error; - acl->aces[2] = nt_create_ace(0x00, 0x0, 0xF003F, "S-1-5-32-544"); - if (!acl->aces[2]) goto error; - acl->aces[3] = nt_create_ace(0x00, 0x0, 0x20019, "S-1-5-12"); - if (!acl->aces[3]) goto error; - acl->aces[4] = nt_create_ace(0x00, 0x0B, 0x10000000, regf->owner_sid_str); - if (!acl->aces[4]) goto error; - acl->aces[5] = nt_create_ace(0x00, 0x0B, 0x10000000, "S-1-5-18"); - if (!acl->aces[5]) goto error; - acl->aces[6] = nt_create_ace(0x00, 0x0B, 0x10000000, "S-1-5-32-544"); - if (!acl->aces[6]) goto error; - acl->aces[7] = nt_create_ace(0x00, 0x0B, 0x80000000, "S-1-5-12"); - if (!acl->aces[7]) goto error; - return acl; - - error: - if (acl) nt_delete_acl(acl); - return NULL; -} - -/* - * Create a default security descriptor. We pull in things from env - * if need be - */ -SEC_DESC *nt_create_def_sec_desc(REGF *regf) -{ - SEC_DESC *tmp; - - tmp = (SEC_DESC *)malloc(sizeof(SEC_DESC)); - if (!tmp) return NULL; - - tmp->rev = 1; - tmp->type = 0x8004; - if (!string_to_sid(&tmp->owner, "S-1-5-32-544")) goto error; - if (!string_to_sid(&tmp->group, "S-1-5-18")) goto error; - tmp->sacl = NULL; - tmp->dacl = nt_create_default_acl(regf); - - return tmp; - - error: - if (tmp) nt_delete_sec_desc(tmp); + if (tmp) free(tmp); return NULL; } -/* - * We will implement inheritence that is based on what the parent's SEC_DESC - * says, but the Owner and Group SIDs can be overwridden from the command line - * and additional ACEs can be applied from the command line etc. - */ -KEY_SEC_DESC *nt_inherit_security(REG_KEY *key) -{ - - if (!key) return NULL; - return key->security; -} - -/* - * Create an initial security descriptor and init other structures, if needed - * We assume that the initial security stuff is empty ... - */ -KEY_SEC_DESC *nt_create_init_sec(REGF *regf) -{ - KEY_SEC_DESC *tsec = NULL; - - tsec = (KEY_SEC_DESC *)malloc(sizeof(KEY_SEC_DESC)); - if (!tsec) return NULL; - - tsec->ref_cnt = 1; - tsec->state = SEC_DESC_NBK; - tsec->offset = 0; - - tsec->sec_desc = regf->def_sec_desc; - - return tsec; -} - -/* - * Add a sub-key - */ -REG_KEY *nt_add_reg_key_list(REGF *regf, REG_KEY *key, char * name, int create) +REG_KEY *nt_add_reg_key(REG_KEY *key, char *name, int create); +REG_KEY *nt_add_reg_key_list(KEY_LIST *list, char * name, REG_KEY *parent, int create) { int i; - REG_KEY *ret = NULL, *tmp = NULL; - KEY_LIST *list; + REG_KEY *ret; char *lname, *c1, *c2; - if (!key || !name || !*name) return NULL; - - list = key->sub_keys; - if (!list) { /* Create an empty list */ - - list = (KEY_LIST *)malloc(sizeof(KEY_LIST) + (REG_KEY_LIST_SIZE - 1) * sizeof(REG_KEY *)); - list->key_count = 0; - list->max_keys = REG_KEY_LIST_SIZE; + if (!list || !name || !*name) return NULL; + for (i = 0; i < list->key_count; i++) { + if ((ret = nt_add_reg_key(list->keys[i], name, create))) + return ret; } + /* + * If we reach here we could not find the the first component + * so create it ... + */ + lname = strdup(name); if (!lname) return NULL; @@ -1361,86 +1000,30 @@ REG_KEY *nt_add_reg_key_list(REGF *regf, REG_KEY *key, char * name, int create) c2++; } - for (i = 0; i < list->key_count; i++) { - if (strcmp(list->keys[i]->name, c1) == 0) { - ret = nt_add_reg_key_list(regf, list->keys[i], c2, create); - free(lname); - return ret; - } - } - - /* - * If we reach here we could not find the the first component - * so create it ... - */ - if (list->key_count < list->max_keys){ list->key_count++; } else { /* Create more space in the list ... */ - if (!(list = (KEY_LIST *)realloc(list, sizeof(KEY_LIST) + - (list->max_keys + REG_KEY_LIST_SIZE - 1) - * sizeof(REG_KEY *)))); - goto error; - - list->max_keys += REG_KEY_LIST_SIZE; - list->key_count++; - } - - /* - * add the new key at the new slot - * FIXME: Sort the list someday - */ - - /* - * We want to create the key, and then do the rest - */ - - tmp = (REG_KEY *)malloc(sizeof(REG_KEY)); - - bzero(tmp, sizeof(REG_KEY)); - tmp->name = strdup(c1); - if (!tmp->name) goto error; - tmp->owner = key; - tmp->type = REG_SUB_KEY; - /* - * Next, pull security from the parent, but override with - * anything passed in on the command line - */ - tmp->security = nt_inherit_security(key); - - list->keys[list->key_count - 1] = tmp; - - if (c2) { - ret = nt_add_reg_key_list(regf, key, c2, True); } - if (lname) free(lname); - - return ret; - + return NULL; error: - if (tmp) free(tmp); if (lname) free(lname); return NULL; } -/* - * This routine only adds a key from the root down. - * It calls helper functions to handle sub-key lists and sub-keys - */ -REG_KEY *nt_add_reg_key(REGF *regf, char *name, int create) +REG_KEY *nt_add_reg_key(REG_KEY *key, char *name, int create) { char *lname = NULL, *c1, *c2; - REG_KEY * tmp = NULL; + REG_KEY * tmp; /* * Look until we hit the first component that does not exist, and * then add from there. However, if the first component does not * match and the path we are given is the root, then it must match */ - if (!regf || !name || !*name) return NULL; + if (!key || !name || !*name) return NULL; lname = strdup(name); if (!lname) return NULL; @@ -1453,45 +1036,38 @@ REG_KEY *nt_add_reg_key(REGF *regf, char *name, int create) } /* - * If the root does not exist, create it and make it equal to the - * first component ... + * If we don't match, then we have to return error ... + * If we do match on this component, check the next one in the + * list, and if not found, add it ... short circuit, add all the + * way down */ - if (!regf->root) { - - tmp = (REG_KEY *)malloc(sizeof(REG_KEY)); - if (!tmp) goto error; - bzero(tmp, sizeof(REG_KEY)); - tmp->name = strdup(c1); - if (!tmp->name) goto error; - tmp->security = nt_create_init_sec(regf); - if (!tmp->security) goto error; - regf->root = tmp; - - } - else { - /* - * If we don't match, then we have to return error ... - * If we do match on this component, check the next one in the - * list, and if not found, add it ... short circuit, add all the - * way down - */ - - if (strcmp(c1, regf->root->name) != 0) - goto error; - } - - tmp = nt_add_reg_key_list(regf, regf->root, c2, True); + if (strcmp(c1, key->name) != 0) + goto error; + + tmp = nt_add_reg_key_list(key->sub_keys, c2, key, True); free(lname); return tmp; error: - if (tmp) free(tmp); if (lname) free(lname); return NULL; } /* + * 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 @@ -1523,6 +1099,22 @@ REG_KEY *nt_add_reg_key(REGF *regf, char *name, int create) #define REGF_HDR_BLKSIZ 0x1000 +/* + * 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 CVAL(buf) ((unsigned char)*((unsigned char *)(buf))) + #define OFF(f) ((f) + REGF_HDR_BLKSIZ + 4) #define LOCN(base, f) ((base) + OFF(f)) @@ -1584,7 +1176,6 @@ int data_to_ascii(unsigned char *datap, int len, int type, char *ascii, int asci switch (type) { case REG_TYPE_REGSZ: if (verbose) fprintf(stderr, "Len: %d\n", len); - /* FIXME. This has to be fixed. It has to be UNICODE */ return uni_to_ascii(datap, ascii, len, ascii_max); break; @@ -1643,7 +1234,6 @@ REGF *nt_create_regf(void) REGF *tmp = (REGF *)malloc(sizeof(REGF)); if (!tmp) return tmp; bzero(tmp, sizeof(REGF)); - tmp->owner_sid_str = def_owner_sid_str; return tmp; } @@ -1656,6 +1246,12 @@ int nt_free_regf(REGF *regf) 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, False); /* Free the tree */ free(regf->sk_map); regf->sk_count = regf->sk_map_size = 0; @@ -1800,7 +1396,6 @@ KEY_SEC_DESC *lookup_create_sec_key(REGF *regf, SK_MAP *sk_map, int sk_off) if (!tmp) { return NULL; } - bzero(tmp, sizeof(KEY_SEC_DESC)); /* Neatly sets offset to 0 */ tmp->state = SEC_DESC_RES; if (!alloc_sk_map_entry(regf, tmp, sk_off)) { return NULL; @@ -1865,8 +1460,6 @@ ACL *dup_acl(REG_ACL *acl) tmp->num_aces = num_aces; tmp->refcnt = 1; tmp->rev = SVAL(&acl->rev); - if (verbose) fprintf(stdout, "ACL: refcnt: %u, rev: %u\n", tmp->refcnt, - tmp->rev); ace = (REG_ACE *)&acl->aces; for (i=0; i<num_aces; i++) { tmp->aces[i] = dup_ace(ace); @@ -1889,14 +1482,6 @@ SEC_DESC *process_sec_desc(REGF *regf, REG_SEC_DESC *sec_desc) tmp->rev = SVAL(&sec_desc->rev); tmp->type = SVAL(&sec_desc->type); - if (verbose) fprintf(stdout, "SEC_DESC Rev: %0X, Type: %0X\n", - tmp->rev, tmp->type); - if (verbose) fprintf(stdout, "SEC_DESC Owner Off: %0X\n", - IVAL(&sec_desc->owner_off)); - if (verbose) fprintf(stdout, "SEC_DESC Group Off: %0X\n", - IVAL(&sec_desc->group_off)); - if (verbose) fprintf(stdout, "SEC_DESC DACL Off: %0X\n", - IVAL(&sec_desc->dacl_off)); tmp->owner = dup_sid((DOM_SID *)((char *)sec_desc + IVAL(&sec_desc->owner_off))); if (!tmp->owner) { free(tmp); @@ -2070,13 +1655,7 @@ VAL_KEY *process_vk(REGF *regf, VK_HDR *vk_hdr, int size) char *dat_ptr = LOCN(regf->base, dat_off); bcopy(dat_ptr, dtmp, dat_len); } - else { /* The data is in the offset or type */ - /* - * FIXME. - * Some registry files seem to have wierd fields. If top bit is set, - * but len is 0, the type seems to be the value ... - * Not sure how to handle this last type for the moment ... - */ + else { /* The data is in the offset */ dat_len = dat_len & 0x7FFFFFFF; bcopy(&dat_off, dtmp, dat_len); } @@ -2095,7 +1674,7 @@ VAL_KEY *process_vk(REGF *regf, VK_HDR *vk_hdr, int size) return tmp; error: - if (tmp) nt_delete_val_key(tmp); + /* XXX: FIXME, free the partially allocated struct */ return NULL; } @@ -2131,7 +1710,6 @@ VAL_LIST *process_vl(REGF *regf, VL_TYPE vl, int count, int size) } tmp->val_count = count; - tmp->max_vals = count; return tmp; @@ -2160,7 +1738,7 @@ KEY_LIST *process_lf(REGF *regf, LF_HDR *lf_hdr, int size, REG_KEY *parent) assert(size < 0); count = SVAL(&lf_hdr->key_count); - if (verbose) fprintf(stdout, "Key Count: %u\n", count); + if (count <= 0) return NULL; /* Now, we should allocate a KEY_LIST struct and fill it in ... */ @@ -2177,7 +1755,6 @@ KEY_LIST *process_lf(REGF *regf, LF_HDR *lf_hdr, int size, REG_KEY *parent) NK_HDR *nk_hdr; nk_off = IVAL(&lf_hdr->hr[i].nk_off); - if (verbose) fprintf(stdout, "NK Offset: %0X\n", 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), parent); if (!tmp->keys[i]) { @@ -2193,7 +1770,7 @@ KEY_LIST *process_lf(REGF *regf, LF_HDR *lf_hdr, int size, REG_KEY *parent) } /* - * This routine is passed an NK_HDR pointer and retrieves the entire tree + * This routine is passed a NK_HDR pointer and retrieves the entire tree * from there down. It returns a REG_KEY *. */ REG_KEY *nt_get_key_tree(REGF *regf, NK_HDR *nk_hdr, int size, REG_KEY *parent) @@ -2269,7 +1846,6 @@ REG_KEY *nt_get_key_tree(REGF *regf, NK_HDR *nk_hdr, int size, REG_KEY *parent) clsnam_off = IVAL(&nk_hdr->clsnam_off); clsnamep = LOCN(regf->base, clsnam_off); - if (verbose) fprintf(stdout, "Class Name Offset: %0X\n", clsnam_off); bzero(cls_name, clsname_len); uni_to_ascii(clsnamep, cls_name, sizeof(cls_name), clsname_len); @@ -2296,10 +1872,9 @@ REG_KEY *nt_get_key_tree(REGF *regf, NK_HDR *nk_hdr, int size, REG_KEY *parent) own_off = IVAL(&nk_hdr->own_off); own = (REG_KEY *)LOCN(regf->base, own_off); - if (verbose) fprintf(stdout, "Owner Offset: %0X\n", own_off); - if (verbose) fprintf(stdout, " Owner locn: %0X, Our locn: %0X\n", - (unsigned int)own, (unsigned int)nk_hdr); + if (verbose) fprintf(stdout, " Owner offset: %0X, Our Offset: %0X\n", + own, nk_hdr); /* * We should verify that the owner field is correct ... @@ -2313,12 +1888,11 @@ REG_KEY *nt_get_key_tree(REGF *regf, NK_HDR *nk_hdr, int size, REG_KEY *parent) */ val_count = IVAL(&nk_hdr->val_cnt); - if (verbose) fprintf(stdout, "Val Count: %d\n", val_count); + if (val_count) { val_off = IVAL(&nk_hdr->val_off); vl = (VL_TYPE *)LOCN(regf->base, val_off); - if (verbose) fprintf(stdout, "Val List Offset: %0X\n", val_off); tmp->values = process_vl(regf, *vl, val_count, BLK_SIZE(vl)); if (!tmp->values) { @@ -2333,7 +1907,6 @@ REG_KEY *nt_get_key_tree(REGF *regf, NK_HDR *nk_hdr, int size, REG_KEY *parent) sk_off = IVAL(&nk_hdr->sk_off); sk_hdr = (SK_HDR *)LOCN(regf->base, sk_off); - if (verbose) fprintf(stdout, "SK Offset: %0X\n", sk_off); if (sk_off != -1) { @@ -2342,7 +1915,6 @@ REG_KEY *nt_get_key_tree(REGF *regf, NK_HDR *nk_hdr, int size, REG_KEY *parent) } lf_off = IVAL(&nk_hdr->lf_off); - if (verbose) fprintf(stdout, "SubKey list offset: %0X\n", lf_off); /* * No more subkeys if lf_off == -1 @@ -2417,21 +1989,7 @@ int nt_load_registry(REGF *regf) * Get a pointer to the first key from the hreg_hdr */ - if (verbose) fprintf(stdout, "First Key: %0X\n", - IVAL(®f_hdr->first_key)); - first_key = (NK_HDR *)LOCN(regf->base, IVAL(®f_hdr->first_key)); - if (verbose) fprintf(stdout, "First Key Offset: %0X\n", - IVAL(®f_hdr->first_key)); - - if (verbose) fprintf(stdout, "Data Block Size: %d\n", - IVAL(®f_hdr->dblk_size)); - - if (verbose) fprintf(stdout, "Offset to next hbin block: %0X\n", - IVAL(&hbin_hdr->off_to_next)); - - if (verbose) fprintf(stdout, "HBIN block size: %0X\n", - IVAL(&hbin_hdr->blk_size)); /* * Now, get the registry tree by processing that NK recursively @@ -2441,575 +1999,14 @@ int nt_load_registry(REGF *regf) assert(regf->root != NULL); - /* - * Unmap the registry file, as we might want to read in another - * tree etc. - */ - - if (regf->base) munmap(regf->base, regf->sbuf.st_size); - regf->base = NULL; - close(regf->fd); /* Ignore the error :-) */ - return 1; } /* - * Allocate a new hbin block, set up the header for the block etc - */ -HBIN_BLK *nt_create_hbin_blk(REGF *regf, int size) -{ - HBIN_BLK *tmp; - HBIN_HDR *hdr; - - if (!regf || !size) return NULL; - - /* Round size up to multiple of REGF_HDR_BLKSIZ */ - - size = (size + (REGF_HDR_BLKSIZ - 1)) & ~(REGF_HDR_BLKSIZ - 1); - - tmp = (HBIN_BLK *)malloc(sizeof(HBIN_BLK)); - bzero(tmp, sizeof(HBIN_BLK)); - - tmp->data = malloc(size); - if (!tmp->data) goto error; - - bzero(tmp->data, size); /* Make it pristine */ - - tmp->size = size; - tmp->file_offset = regf->blk_tail->file_offset + regf->blk_tail->size; - - tmp->free_space = size - (sizeof(HBIN_HDR) - sizeof(HBIN_SUB_HDR)); - tmp->fsp_off = size - tmp->free_space; - - /* - * Now, build the header in the data block - */ - hdr = (HBIN_HDR *)tmp->data; - hdr->HBIN_ID = REG_HBIN_ID; - hdr->off_from_first = tmp->file_offset - REGF_HDR_BLKSIZ; - hdr->off_to_next = tmp->size; - hdr->blk_size = tmp->size; - - /* - * Now link it in - */ - - regf->blk_tail->next = tmp; - regf->blk_tail = tmp; - if (!regf->free_space) regf->free_space = tmp; - - return tmp; - error: - if (tmp) free(tmp); - return NULL; -} - -/* - * Allocate a unit of space ... and return a pointer as function param - * and the block's offset as a side effect - */ -void *nt_alloc_regf_space(REGF *regf, int size, int *off) -{ - int tmp = 0; - void *ret = NULL; - HBIN_BLK *blk; - - if (!regf || !size || !off) return NULL; - - assert(regf->blk_head != NULL); - - /* - * round up size to include header and then to 8-byte boundary - */ - size = (size + 4 + 7) & ~7; - - /* - * Check if there is space, if none, grab a block - */ - if (!regf->free_space) { - if (!nt_create_hbin_blk(regf, REGF_HDR_BLKSIZ)) - return NULL; - } - - /* - * Now, chain down the list of blocks looking for free space - */ - - for (blk = regf->free_space; blk != NULL; blk = blk->next) { - if (blk->free_space <= size) { - tmp = blk->file_offset + blk->fsp_off - REGF_HDR_BLKSIZ; - ret = blk->data + blk->fsp_off; - blk->free_space -= size; - blk->fsp_off += size; - - /* Insert the header */ - ((HBIN_SUB_HDR *)ret)->dblocksize = -size; - - /* - * Fix up the free space ptr - * If it is NULL, we fix it up next time - */ - - if (!blk->free_space) - regf->free_space = blk->next; - - *off = tmp; - return (((char *)ret)+4);/* The pointer needs to be to the data struct */ - } - } - - /* - * If we got here, we need to add another block, which might be - * larger than one block -- deal with that later - */ - if (nt_create_hbin_blk(regf, REGF_HDR_BLKSIZ)) { - blk = regf->free_space; - tmp = blk->file_offset + blk->fsp_off - REGF_HDR_BLKSIZ; - ret = blk->data + blk->fsp_off; - blk->free_space -= size; - blk->fsp_off += size; - - /* Insert the header */ - ((HBIN_SUB_HDR *)ret)->dblocksize = -size; - - /* - * Fix up the free space ptr - * If it is NULL, we fix it up next time - */ - - if (!blk->free_space) - regf->free_space = blk->next; - - *off = tmp; - return (((char *)ret) + 4);/* The pointer needs to be to the data struct */ - } - - return NULL; -} - -/* - * Compute the size of a SID stored ... - */ - -unsigned int sid_size(DOM_SID *sid) -{ - unsigned int size; - - if (!sid) return 0; - - size = 8 + (sid->auths * sizeof(unsigned int)); - - return size; -} - -/* - * Compute the size of an ACE on disk from its components - */ - -unsigned int ace_size(ACE *ace) -{ - unsigned int size; - - if (!ace) return 0; - - size = 8 + sid_size(ace->trustee); - - return size; -} - -/* - * Compute the size of an ACL from its components ... - */ -unsigned int acl_size(ACL *acl) -{ - unsigned int size; - int i; - - if (!acl) return 0; - - size = 8; - for (i = 0; i < acl->num_aces; i++) - size += ace_size(acl->aces[i]); - - return size; -} - -/* - * Compute the size of the sec desc as a self-relative SD - */ -unsigned int sec_desc_size(SEC_DESC *sd) -{ - unsigned int size; - - if (!sd) return 0; - - size = 20; - - if (sd->owner) size += sid_size(sd->owner); - if (sd->group) size += sid_size(sd->group); - if (sd->sacl) size += acl_size(sd->sacl); - if (sd->dacl) size += acl_size(sd->dacl); - - return size; -} - -/* - * Store a SID at the location provided - */ - -int nt_store_SID(REGF *regf, DOM_SID *sid, unsigned char *locn) -{ - int i; - unsigned char *p = locn; - - if (!regf || !sid || !locn) return 0; - - *p = sid->ver; p++; - *p = sid->auths; p++; - - for (i=0; i < 6; i++) { - *p = sid->auth[i]; p++; - } - - for (i=0; i < sid->auths; i++) { - SIVAL(p, sid->sub_auths[i]); p+=4; - } - - return p - locn; - -} - -int nt_store_ace(REGF *regf, ACE *ace, unsigned char *locn) -{ - int size = 0; - REG_ACE *reg_ace = (REG_ACE *)locn; - unsigned char *p; - - if (!regf || !ace || !locn) return 0; - - reg_ace->type = ace->type; - reg_ace->flags = ace->flags; - - /* Deal with the length when we have stored the SID */ - - p = (unsigned char *)®_ace->perms; - - SIVAL(p, ace->perms); p += 4; - - size = nt_store_SID(regf, ace->trustee, p); - - size += 8; /* Size of the fixed header */ - - p = (unsigned char *)®_ace->length; - - SSVAL(p, size); - - return size; -} - -/* - * Store an ACL at the location provided - */ - -int nt_store_acl(REGF *regf, ACL *acl, unsigned char *locn) -{ - int size = 0, i; - unsigned char *p = locn, *s; - - if (!regf || !acl || !locn) return 0; - - /* - * Now store the header and then the ACEs ... - */ - - SSVAL(p, acl->rev); - - p += 2; s = p; /* Save this for the size field */ - - p += 2; - - SIVAL(p, acl->num_aces); - - p += 4; - - for (i = 0; i < acl->num_aces; i++) { - size = nt_store_ace(regf, acl->aces[i], p); - p += size; - } - - size = s - locn; - SSVAL(s, size); - return size; -} - -/* - * Flatten and store the Sec Desc - * Windows lays out the DACL first, but since there is no SACL, it might be - * that first, then the owner, then the group SID. So, we do it that way - * too. - */ -unsigned int nt_store_sec_desc(REGF *regf, SEC_DESC *sd, char *locn) -{ - REG_SEC_DESC *rsd = (REG_SEC_DESC *)locn; - unsigned int size = 0, off = 0; - - if (!regf || !sd || !locn) return 0; - - /* - * Now, fill in the first two fields, then lay out the various fields - * as needed - */ - - rsd->rev = 0x01; - /* Self relative, DACL pres, owner and group not defaulted */ - rsd->type = 0x8004; - - off = 4 * sizeof(DWORD) + 4; - - if (sd->sacl){ - size = nt_store_acl(regf, sd->sacl, (char *)(locn + off)); - rsd->sacl_off = off; - } - else - rsd->sacl_off = 0; - - off += size; - - if (sd->dacl) { - rsd->dacl_off = off; - size = nt_store_acl(regf, sd->dacl, (char *)(locn + off)); - } - else { - rsd->dacl_off = 0; - } - - off += size; - - /* Now the owner and group SIDs */ - - if (sd->owner) { - rsd->owner_off = off; - size = nt_store_SID(regf, sd->owner, (char *)(locn + off)); - } - else { - rsd->owner_off = 0; - } - - off += size; - - if (sd->group) { - rsd->group_off = off; - size = nt_store_SID(regf, sd->group, (char *)(locn + off)); - } - else { - rsd->group_off = 0; - } - - off += size; - - return size; -} - -/* - * Store the security information - * - * If it has already been stored, just get its offset from record - * otherwise, store it and record its offset - */ - -unsigned int nt_store_security(REGF *regf, KEY_SEC_DESC *sec) -{ - int size = 0; - unsigned int sk_off; - SK_HDR *sk_hdr; - - if (sec->offset) return sec->offset; - - /* - * OK, we don't have this one in the file yet. We must compute the - * size taken by the security descriptor as a self-relative SD, which - * means making one pass over each structure and figuring it out - */ - - size = sec_desc_size(sec->sec_desc); - - /* Allocate that much space */ - - sk_hdr = nt_alloc_regf_space(regf, size, &sk_off); - sec->sk_hdr = sk_hdr; - - if (!sk_hdr) return 0; - - /* Now, lay out the sec_desc in the space provided */ - - sk_hdr->SK_ID = REG_SK_ID; - - /* - * We can't deal with the next and prev offset in the SK_HDRs until the - * whole tree has been stored, then we can go and deal with them - */ - - sk_hdr->ref_cnt = sec->ref_cnt; - sk_hdr->rec_size = size; /* Is this correct */ - - /* Now, lay out the sec_desc */ - - if (!nt_store_sec_desc(regf, sec->sec_desc, (char *)&sk_hdr->sec_desc)) - return 0; - - return sk_off; - -} - -/* - * Store a VAL LIST - */ - -int nt_store_val_list(REGF *regf, VAL_LIST * values) -{ - - return 0; -} - -/* - * Store a KEY in the file ... - * - * We store this depth first, and defer storing the lf struct until - * all the sub-keys have been stored. - * - * We store the NK hdr, any SK header, class name, and VK structure, then - * recurse down the LF structures ... - * - * We return the offset of the NK struct - * FIXME, FIXME, FIXME: Convert to using SIVAL and SSVAL ... - */ -int nt_store_reg_key(REGF *regf, REG_KEY *key) -{ - NK_HDR *nk_hdr; - unsigned int nk_off, sk_off, val_off, clsnam_off, size; - - if (!regf || !key) return 0; - - size = sizeof(NK_HDR) + strlen(key->name) - 1; - nk_hdr = nt_alloc_regf_space(regf, size, &nk_off); - if (!nk_hdr) goto error; - - key->offset = nk_off; /* We will need this later */ - - /* - * Now fill in each field etc ... - */ - - nk_hdr->NK_ID = REG_NK_ID; - if (key->type == REG_ROOT_KEY) - nk_hdr->type = 0x2C; - else - nk_hdr->type = 0x20; - - /* FIXME: Fill in the time of last update */ - - if (key->type != REG_ROOT_KEY) - nk_hdr->own_off = key->owner->offset; - - if (key->sub_keys) - nk_hdr->subk_num = key->sub_keys->key_count; - - /* - * Now, process the Sec Desc and then store its offset - */ - - sk_off = nt_store_security(regf, key->security); - nk_hdr->sk_off = sk_off; - - /* - * Then, store the val list and store its offset - */ - if (key->values) { - nk_hdr->val_cnt = key->values->val_count; - nk_hdr->val_off = nt_store_val_list(regf, key->values); - } - else { - nk_hdr->val_off = -1; - nk_hdr->val_cnt = 0; - } - - /* - * Finally, store the subkeys, and their offsets - */ - - error: - return 0; -} - -/* - * Store the registry header ... - * We actually create the registry header block and link it to the chain - * of output blocks. - */ -REGF_HDR *nt_get_reg_header(REGF *regf) -{ - HBIN_BLK *tmp = NULL; - - tmp = (HBIN_BLK *)malloc(sizeof(HBIN_BLK)); - if (!tmp) return 0; - - bzero(tmp, sizeof(HBIN_BLK)); - tmp->type = REG_OUTBLK_HDR; - tmp->size = REGF_HDR_BLKSIZ; - tmp->data = malloc(REGF_HDR_BLKSIZ); - if (!tmp->data) goto error; - - bzero(tmp->data, REGF_HDR_BLKSIZ); /* Make it pristine, unlike Windows */ - regf->blk_head = regf->blk_tail = tmp; - - return (REGF_HDR *)tmp->data; - - error: - if (tmp) free(tmp); - return NULL; -} - -/* - * Store the registry in the output file - * We write out the header and then each of the keys etc into the file - * We have to flatten the data structure ... - * - * The structures are stored in a depth-first fashion, with all records - * aligned on 8-byte boundaries, with sub-keys and values layed down before - * the lists that contain them. SK records are layed down first, however. - * The lf fields are layed down after all sub-keys have been layed down, it - * seems, including the whole tree associated with each sub-key. + * Story the registry in the output file */ int nt_store_registry(REGF *regf) { - REGF_HDR *reg; - int fkey, fd; - - /* - * Get a header ... and partially fill it in ... - */ - reg = nt_get_reg_header(regf); - - /* - * Store the first key, which will store the whole thing - */ - fkey = nt_store_reg_key(regf, regf->root); - - /* - * At this point we have the registry as a series of blocks, so - * run down that series of blocks and save them ... - */ - - if (!regf->outfile_name) { - fprintf(stderr, "Cannot write file without a name!\n"); - return 0; - } - - if ((fd = open(regf->outfile_name, O_WRONLY, 0666)) < 0) { - fprintf(stderr, "Unable to create file %s: %s\n", regf->outfile_name, - strerror(errno)); - return 0; - } return 1; } @@ -3067,15 +2064,6 @@ typedef struct cmd_line { char *line; } CMD_LINE; -void free_val_spec_list(VAL_SPEC_LIST *vl) -{ - if (!vl) return; - if (vl->name) free(vl->name); - if (vl->val) free(vl->val); - free(vl); - -} - /* * Some routines to handle lines of info in the command files */ @@ -3212,9 +2200,6 @@ struct cmd_line *get_cmd_line(int fd) * * If it parsed OK, return the <value-name> as a string, and the * value type and value-string in parameters. - * - * The value name can be empty. There can only be one empty name in - * a list of values. A value of - removes the value entirely. */ char *dup_str(char *s, int len) @@ -3273,8 +2258,6 @@ int parse_value_type(char *tstr) return REG_TYPE_REGSZ; else if (strcmp(tstr, "REG_MULTI_SZ") == 0) return REG_TYPE_MULTISZ; - else if (strcmp(tstr, "-") == 0) - return REG_TYPE_DELETE; return 0; } @@ -3312,16 +2295,14 @@ char *parse_value(struct cmd_line *cl, int *vtype, char **val) while (*tstr == ' ') tstr++; /* Skip leading white space */ p2 = strchr(p2, ':'); - if (p2) { - *p2 = 0; p2++; /* split on the : */ - } + if (!p2) goto error; + + *p2 = 0; p2++; /* split on the : */ *vtype = parse_value_type(tstr); if (!vtype) goto error; - if (!p2 || !*p2) return nstr; - /* Now, parse the value string. It should return a newly malloc'd string */ while (*p2 == ' ') p2++; /* Skip leading space */ @@ -3486,7 +2467,6 @@ void trim_trailing_spaces(struct cmd_line *cl) * value ::= <value-name>=<value-type>':'<value-string> * <value-name> is some path, possibly enclosed in quotes ... * We alctually look for the next key to terminate a previous key - * if <value-type> == '-', then it is a delete type. */ CMD *regedit4_get_cmd(int fd) { @@ -3502,19 +2482,8 @@ CMD *regedit4_get_cmd(int fd) cmd->cmd = CMD_NONE; cmd->key = NULL; - cmd->val_count = 0; cmd->val_spec_list = cmd->val_spec_last = NULL; - while ((cl = get_cmd_line(fd))) { - - /* - * If it is an empty command line, and we already have a key - * then exit from here ... FIXME: Clean up the parser - */ - - if (cl->line_len == 0 && cmd->key) { - free_cmd_line(cl); - break; - } + while (cl = get_cmd_line(fd)) { strip_comment(cl); /* remove anything beyond a comment char */ trim_trailing_spaces(cl); @@ -3545,7 +2514,6 @@ CMD *regedit4_get_cmd(int fd) vl = (struct val_spec_list *)malloc(sizeof(struct val_spec_list)); if (!vl) goto error; vl->next = NULL; - vl->val = NULL; vl->name = parse_value(cl, &vl->type, &vl->val); if (!vl->name) goto error; if (cmd->val_spec_list == NULL) { @@ -3717,7 +2685,7 @@ int print_key(const char *path, char *name, char *class_name, int root, int terminal, int vals) { - if (full_print || terminal) fprintf(stdout, "[%s%s]\n", path, name); + /*if (terminal)*/ fprintf(stdout, "[%s%s]\n", path, name); return 1; } @@ -3869,10 +2837,9 @@ int print_val(const char *path, char *val_name, int val_type, int data_len, void usage(void) { - fprintf(stderr, "Usage: editreg [-f] [-v] [-p] [-k] [-s] [-c <command-file>] <registryfile>\n"); + fprintf(stderr, "Usage: editreg [-v] [-p] [-k] [-s] [-c <command-file>] <registryfile>\n"); fprintf(stderr, "Version: 0.1\n\n"); fprintf(stderr, "\n\t-v\t sets verbose mode"); - fprintf(stderr, "\n\t-f\t sets full print mode where non-terminals are printed"); fprintf(stderr, "\n\t-p\t prints the registry"); fprintf(stderr, "\n\t-s\t prints security descriptors"); fprintf(stderr, "\n\t-c <command-file>\t specifies a command file"); @@ -3886,11 +2853,10 @@ int main(int argc, char *argv[]) extern int optind; int opt, print_keys = 0; int regf_opt = 1; /* Command name */ - int commands = 0, modified = 0; + int commands = 0; char *cmd_file_name = NULL; char *out_file_name = NULL; CMD_FILE *cmd_file = NULL; - DOM_SID *lsid; if (argc < 2) { usage(); @@ -3901,7 +2867,7 @@ int main(int argc, char *argv[]) * Now, process the arguments */ - while ((opt = getopt(argc, argv, "fspvko:O:c:")) != EOF) { + while ((opt = getopt(argc, argv, "spvko:c:")) != EOF) { switch (opt) { case 'c': commands = 1; @@ -3909,29 +2875,11 @@ int main(int argc, char *argv[]) regf_opt += 2; break; - case 'f': - full_print = 1; - regf_opt++; - break; - case 'o': out_file_name = optarg; regf_opt += 2; break; - case 'O': - def_owner_sid_str = strdup(optarg); - regf_opt += 2; - if (!string_to_sid(&lsid, def_owner_sid_str)) { - fprintf(stderr, "Default Owner SID: %s is incorrectly formatted\n", - def_owner_sid_str); - free(def_owner_sid_str); - def_owner_sid_str = NULL; - } - else - nt_delete_sid(lsid); - break; - case 'p': print_keys++; regf_opt++; @@ -3939,7 +2887,6 @@ int main(int argc, char *argv[]) case 's': print_security++; - full_print++; regf_opt++; break; @@ -3959,17 +2906,6 @@ int main(int argc, char *argv[]) } } - /* - * We only want to complain about the lack of a default owner SID if - * we need one. This approximates that need - */ - if (!def_owner_sid_str) { - def_owner_sid_str = "S-1-5-21-1-2-3-4"; - if (out_file_name || verbose) - fprintf(stderr, "Warning, default owner SID not set. Setting to %s\n", - def_owner_sid_str); - } - if ((regf = nt_create_regf()) == NULL) { fprintf(stderr, "Could not create registry object: %s\n", strerror(errno)); exit(2); @@ -4010,41 +2946,10 @@ int main(int argc, char *argv[]) * Now, apply the requests to the tree ... */ switch (cmd->cmd) { - case CMD_ADD_KEY: { - REG_KEY *tmp = NULL; - - tmp = nt_find_key_by_name(regf->root, cmd->key); - - /* If we found it, apply the other bits, else create such a key */ - - if (!tmp) { - tmp = nt_add_reg_key(regf, cmd->key, True); - modified = 1; - } - - while (cmd->val_count) { - VAL_SPEC_LIST *val = cmd->val_spec_list; - VAL_KEY *reg_val = NULL; - - if (val->type == REG_TYPE_DELETE) { - reg_val = nt_delete_reg_value(tmp, val -> name); - if (reg_val) nt_delete_val_key(reg_val); - modified = 1; - } - else { - reg_val = nt_add_reg_value(tmp, val->name, val->type, - val->val); - modified = 1; - } - - cmd->val_spec_list = val->next; - free_val_spec_list(val); - cmd->val_count--; - } + case CMD_ADD_KEY: break; - } - + case CMD_DEL_KEY: /* * Any value does not matter ... @@ -4052,7 +2957,6 @@ int main(int argc, char *argv[]) */ nt_delete_key_by_name(regf, cmd->key); - modified = 1; break; } } @@ -4068,13 +2972,5 @@ int main(int argc, char *argv[]) nt_key_iterator(regf, regf->root, 0, "", print_key, print_sec, print_val); } - /* - * If there was an out_file_name and the tree was modified, print it - */ - if (modified && out_file_name) - if (!nt_store_registry(regf)) { - fprintf(stdout, "Error storing registry\n"); - } - return 0; } diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c index 203d849786..d775135e0a 100644 --- a/source3/utils/net_ads.c +++ b/source3/utils/net_ads.c @@ -124,7 +124,6 @@ static ADS_STRUCT *ads_startup(void) ADS_STATUS status; BOOL need_password = False; BOOL second_time = False; - char *realm; ads = ads_init(NULL, NULL, opt_host); @@ -151,16 +150,6 @@ retry: ads->auth.user_name = strdup(opt_user_name); - /* - * If the username is of the form "name@realm", - * extract the realm and convert to upper case. - */ - if ((realm = strchr(ads->auth.user_name, '@'))) { - *realm++ = '\0'; - ads->auth.realm = strdup(realm); - strupper(ads->auth.realm); - } - status = ads_connect(ads); if (!ADS_ERR_OK(status)) { if (!need_password && !second_time) { @@ -230,7 +219,7 @@ static BOOL usergrp_display(char *field, void **values, void *data_area) if (!field) { /* must be end of record */ if (!strchr_m(disp_fields[0], '$')) { if (disp_fields[1]) - d_printf("%-21.21s %-50.50s\n", + d_printf("%-21.21s %s\n", disp_fields[0], disp_fields[1]); else d_printf("%s\n", disp_fields[0]); diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c index e3e79b0e6c..f9efe2d688 100644 --- a/source3/utils/net_rpc.c +++ b/source3/utils/net_rpc.c @@ -235,14 +235,25 @@ int net_rpc_changetrustpw(int argc, const char **argv) * @return Normal NTSTATUS return. **/ -static NTSTATUS rpc_join_oldstyle_internals(const DOM_SID *domain_sid, struct cli_state *cli, +static NTSTATUS rpc_oldjoin_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { fstring trust_passwd; unsigned char orig_trust_passwd_hash[16]; NTSTATUS result; + uint32 sec_channel_type; + /* + check what type of join - if the user want's to join as + a BDC, the server must agree that we are a BDC. + */ + if (argc >= 0) { + sec_channel_type = get_sec_channel_type(argv[0]); + } else { + sec_channel_type = get_sec_channel_type(NULL); + } + fstrcpy(trust_passwd, global_myname()); strlower(trust_passwd); @@ -257,11 +268,7 @@ static NTSTATUS rpc_join_oldstyle_internals(const DOM_SID *domain_sid, struct cl result = trust_pw_change_and_store_it(cli, mem_ctx, opt_target_workgroup, orig_trust_passwd_hash, - SEC_CHAN_WKSTA); - - /* SEC_CHAN_WKSTA specified specifically, as you cannot use this - to join a BDC to the domain (MS won't allow it, and is *really* - insecure) */ + sec_channel_type); if (NT_STATUS_IS_OK(result)) printf("Joined domain %s.\n",opt_target_workgroup); @@ -285,40 +292,11 @@ static NTSTATUS rpc_join_oldstyle_internals(const DOM_SID *domain_sid, struct cl * @return A shell status integer (0 for success) **/ -static int net_rpc_join_oldstyle(int argc, const char **argv) -{ - uint32 sec_channel_type; - /* check what type of join */ - if (argc >= 0) { - sec_channel_type = get_sec_channel_type(argv[0]); - } else { - sec_channel_type = get_sec_channel_type(NULL); - } - - if (sec_channel_type != SEC_CHAN_WKSTA) - return 1; - - return run_rpc_command(NULL, PI_NETLOGON, - NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, - rpc_join_oldstyle_internals, - argc, argv); -} - -/** - * Join a domain, the old way. - * - * @param argc Standard main() style argc - * @param argc Standard main() style argv. Initial components are already - * stripped - * - * @return A shell status integer (0 for success) - **/ - static int net_rpc_oldjoin(int argc, const char **argv) { return run_rpc_command(NULL, PI_NETLOGON, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, - rpc_join_oldstyle_internals, + rpc_oldjoin_internals, argc, argv); } @@ -351,13 +329,13 @@ static int rpc_join_usage(int argc, const char **argv) * * Main 'net_rpc_join()' (where the admain username/password is used) is * in net_rpc_join.c - * Assume if a -U is specified, it's the new style, otherwise it's the - * old style. If 'oldstyle' is specfied explicity, do it and don't prompt. + * Try to just change the password, but if that doesn't work, use/prompt + * for a username/password. **/ int net_rpc_join(int argc, const char **argv) { - if ((net_rpc_join_oldstyle(argc, argv) == 0)) + if ((net_rpc_oldjoin(argc, argv) == 0)) return 0; return net_rpc_join_newstyle(argc, argv); @@ -862,7 +840,7 @@ rpc_user_list_internals(const DOM_SID *domain_sid, struct cli_state *cli, unistr2_to_ascii(desc, &(&ctr.sam.info1->str[i])->uni_acct_desc, sizeof(desc)-1); if (opt_long_list_entries) - printf("%-21.21s %-50.50s\n", user, desc); + printf("%-21.21s %s\n", user, desc); else printf("%s\n", user); } diff --git a/source3/utils/pdbedit.c b/source3/utils/pdbedit.c index 4cb3db52b7..3a3d06a645 100644 --- a/source3/utils/pdbedit.c +++ b/source3/utils/pdbedit.c @@ -122,6 +122,12 @@ static int print_sam_info (SAM_ACCOUNT *sam_pwent, BOOL verbosity, BOOL smbpwdst printf ("Unix username: %s\n", pdb_get_username(sam_pwent)); printf ("NT username: %s\n", pdb_get_nt_username(sam_pwent)); printf ("Account Flags: %s\n", pdb_encode_acct_ctrl(pdb_get_acct_ctrl(sam_pwent), NEW_PW_FORMAT_SPACE_PADDED_LEN)); + + if (IS_SAM_UNIX_USER(sam_pwent)) { + uid = pdb_get_uid(sam_pwent); + gid = pdb_get_gid(sam_pwent); + printf ("User ID/Group ID: %d/%d\n", uid, gid); + } printf ("User SID: %s\n", sid_string_static(pdb_get_user_sid(sam_pwent))); printf ("Primary Group SID: %s\n", @@ -155,25 +161,35 @@ static int print_sam_info (SAM_ACCOUNT *sam_pwent, BOOL verbosity, BOOL smbpwdst printf ("Password must change: %s\n", tmp ? http_timestring(tmp) : "0"); } else if (smbpwdstyle) { - char lm_passwd[33]; - char nt_passwd[33]; - - uid = -1; - sid_to_uid(pdb_get_user_sid(sam_pwent), &uid); - pdb_sethexpwd(lm_passwd, pdb_get_lanman_passwd(sam_pwent), pdb_get_acct_ctrl(sam_pwent)); - pdb_sethexpwd(nt_passwd, pdb_get_nt_passwd(sam_pwent), pdb_get_acct_ctrl(sam_pwent)); + if (IS_SAM_UNIX_USER(sam_pwent)) { + char lm_passwd[33]; + char nt_passwd[33]; + + uid = pdb_get_uid(sam_pwent); + pdb_sethexpwd(lm_passwd, + pdb_get_lanman_passwd(sam_pwent), + pdb_get_acct_ctrl(sam_pwent)); + pdb_sethexpwd(nt_passwd, + pdb_get_nt_passwd(sam_pwent), + pdb_get_acct_ctrl(sam_pwent)); - printf("%s:%d:%s:%s:%s:LCT-%08X:\n", - pdb_get_username(sam_pwent), - uid, - lm_passwd, - nt_passwd, - pdb_encode_acct_ctrl(pdb_get_acct_ctrl(sam_pwent),NEW_PW_FORMAT_SPACE_PADDED_LEN), - (uint32)pdb_get_pass_last_set_time(sam_pwent)); + printf("%s:%d:%s:%s:%s:LCT-%08X:\n", + pdb_get_username(sam_pwent), + uid, + lm_passwd, + nt_passwd, + pdb_encode_acct_ctrl(pdb_get_acct_ctrl(sam_pwent),NEW_PW_FORMAT_SPACE_PADDED_LEN), + (uint32)pdb_get_pass_last_set_time(sam_pwent)); + } else { + fprintf(stderr, "Can't output in smbpasswd format, no uid on this record.\n"); + } } else { - uid = -1; - sid_to_uid(pdb_get_user_sid(sam_pwent), &uid); - printf ("%s:%d:%s\n", pdb_get_username(sam_pwent), uid, pdb_get_fullname(sam_pwent)); + if (IS_SAM_UNIX_USER(sam_pwent)) { + printf ("%s:%d:%s\n", pdb_get_username(sam_pwent), pdb_get_uid(sam_pwent), + pdb_get_fullname(sam_pwent)); + } else { + printf ("%s:(null):%s\n", pdb_get_username(sam_pwent), pdb_get_fullname(sam_pwent)); + } } return 0; diff --git a/source3/utils/smbgroupedit.c b/source3/utils/smbgroupedit.c deleted file mode 100644 index 0faa0513ed..0000000000 --- a/source3/utils/smbgroupedit.c +++ /dev/null @@ -1,405 +0,0 @@ -/* - * Unix SMB/CIFS implementation. - * RPC Pipe client / server routines - * Copyright (C) Andrew Tridgell 1992-2000, - * Copyright (C) Jean François Micouleau 1998-2001. - * - * 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" - -/* - * Next two lines needed for SunOS and don't - * hurt anything else... - */ -extern char *optarg; -extern int optind; - -/********************************************************* - Print command usage on stderr and die. -**********************************************************/ -static void usage(void) -{ - if (getuid() == 0) { - printf("smbgroupedit options\n"); - } else { - printf("You need to be root to use this tool!\n"); - } - printf("options:\n"); - printf(" -a group create new group\n"); - printf(" -n group NT group name\n"); - printf(" -p privilege only local\n"); - printf(" -d description group description\n"); - printf(" -v list groups\n"); - printf(" -l long list (include details)\n"); - printf(" -s short list (default)\n"); - printf(" -c SID change group\n"); - printf(" -u unix group\n"); - printf(" -d description group description\n"); - printf(" -r rid RID of new group\n"); - printf(" -x group delete this group\n"); - printf("\n"); - printf(" -t[b|d|l] type: builtin, domain, local \n"); - exit(1); -} - -/********************************************************* - Figure out if the input was an NT group or a SID string. - Return the SID. -**********************************************************/ -static BOOL get_sid_from_input(DOM_SID *sid, char *input) -{ - GROUP_MAP map; - - if (StrnCaseCmp( input, "S-", 2)) { - /* Perhaps its the NT group name? */ - if (!pdb_getgrnam(&map, input, MAPPING_WITHOUT_PRIV)) { - printf("NT Group %s doesn't exist in mapping DB\n", input); - return False; - } else { - *sid = map.sid; - } - } else { - if (!string_to_sid(sid, input)) { - printf("converting sid %s from a string failed!\n", input); - return False; - } - } - return True; -} - -/********************************************************* - add a group. -**********************************************************/ -static int addgroup(gid_t gid, enum SID_NAME_USE sid_type, char *ntgroup, char *ntcomment, char *privilege, uint32 rid) -{ - PRIVILEGE_SET se_priv; - DOM_SID sid; - fstring string_sid; - fstring comment; - - sid_copy(&sid, get_global_sam_sid()); - sid_append_rid(&sid, rid); - - sid_to_string(string_sid, &sid); - - if (ntcomment==NULL) - fstrcpy(comment, "Local Unix group"); - else - fstrcpy(comment, ntcomment); - - init_privilege(&se_priv); - if (privilege!=NULL) - convert_priv_from_text(&se_priv, privilege); - - if(!add_initial_entry(gid, string_sid, sid_type, ntgroup, - comment, se_priv, PR_ACCESS_FROM_NETWORK)) { - printf("adding entry for group %s failed!\n", ntgroup); - free_privilege(&se_priv); - return -1; - } - - free_privilege(&se_priv); - return 0; -} - -/********************************************************* - Change a group. -**********************************************************/ -static int changegroup(char *sid_string, char *group, enum SID_NAME_USE sid_type, char *ntgroup, char *groupdesc, char *privilege) -{ - DOM_SID sid; - GROUP_MAP map; - gid_t gid; - - if (!get_sid_from_input(&sid, sid_string)) { - return -1; - } - - /* Get the current mapping from the database */ - if(!pdb_getgrsid(&map, sid, MAPPING_WITH_PRIV)) { - printf("This SID does not exist in the database\n"); - return -1; - } - - /* If a new Unix group is specified, check and change */ - if (group!=NULL) { - gid=nametogid(group); - if (gid==-1) { - printf("The UNIX group does not exist\n"); - return -1; - } else - map.gid=gid; - } - - /* - * Allow changing of group type only between domain and local - * We disallow changing Builtin groups !!! (SID problem) - */ - if (sid_type==SID_NAME_ALIAS - || sid_type==SID_NAME_DOM_GRP - || sid_type==SID_NAME_UNKNOWN) { - if (map.sid_name_use==SID_NAME_ALIAS - || map.sid_name_use==SID_NAME_DOM_GRP - || map.sid_name_use==SID_NAME_UNKNOWN) { - map.sid_name_use=sid_type; - } else { - printf("cannot change group type to builtin\n"); - }; - } else { - printf("cannot change group type from builtin\n"); - } - - if (ntgroup!=NULL) - fstrcpy(map.nt_name, ntgroup); - - /* Change comment if new one */ - if (groupdesc!=NULL) - fstrcpy(map.comment, groupdesc); - - /* Change the privilege if new one */ - if (privilege!=NULL) - convert_priv_from_text(&map.priv_set, privilege); - - if (!pdb_update_group_mapping_entry(&map)) { - printf("Could not update group database\n"); - free_privilege(&map.priv_set); - return -1; - } - - free_privilege(&map.priv_set); - return 0; -} - -/********************************************************* - Delete the group. -**********************************************************/ -static int deletegroup(char *group) -{ - DOM_SID sid; - - if (!get_sid_from_input(&sid, group)) { - return -1; - } - - if(!pdb_delete_group_mapping_entry(sid)) { - printf("removing group %s from the mapping db failed!\n", group); - return -1; - } - - return 0; -} - -/********************************************************* - List the groups. -**********************************************************/ -static int listgroup(enum SID_NAME_USE sid_type, BOOL long_list) -{ - int entries,i; - GROUP_MAP *map=NULL; - fstring string_sid; - fstring group_type; - fstring priv_text; - - if (!long_list) - printf("NT group (SID) -> Unix group\n"); - - if (!pdb_enum_group_mapping(sid_type, &map, &entries, ENUM_ALL_MAPPED, MAPPING_WITH_PRIV)) - return -1; - - for (i=0; i<entries; i++) { - decode_sid_name_use(group_type, (map[i]).sid_name_use); - sid_to_string(string_sid, &map[i].sid); - convert_priv_to_text(&(map[i].priv_set), priv_text); - free_privilege(&(map[i].priv_set)); - - if (!long_list) - printf("%s (%s) -> %s\n", map[i].nt_name, string_sid, gidtoname(map[i].gid)); - else { - printf("%s\n", map[i].nt_name); - printf("\tSID : %s\n", string_sid); - printf("\tUnix group: %s\n", gidtoname(map[i].gid)); - printf("\tGroup type: %s\n", group_type); - printf("\tComment : %s\n", map[i].comment); - printf("\tPrivilege : %s\n\n", priv_text); - } - } - - return 0; -} - -/********************************************************* - Start here. -**********************************************************/ -int main (int argc, char **argv) -{ - int ch; - BOOL add_group = False; - BOOL view_group = False; - BOOL change_group = False; - BOOL delete_group = False; - BOOL nt_group = False; - BOOL priv = False; - BOOL group_type = False; - BOOL long_list = False; - - char *group = NULL; - char *sid = NULL; - char *ntgroup = NULL; - char *privilege = NULL; - char *groupt = NULL; - char *group_desc = NULL; - - enum SID_NAME_USE sid_type; - uint32 rid = -1; - - setup_logging("groupedit", True); - - if (argc < 2) { - usage(); - return 0; - } - - if (!lp_load(dyn_CONFIGFILE,True,False,False)) { - fprintf(stderr, "Can't load %s - run testparm to debug it\n", - dyn_CONFIGFILE); - exit(1); - } - - if (!init_names()) - exit(1); - - if(!initialize_password_db(True)) { - fprintf(stderr, "Can't setup password database vectors.\n"); - exit(1); - } - - if(get_global_sam_sid()==False) { - fprintf(stderr, "Can not read machine SID\n"); - return 0; - } - - while ((ch = getopt(argc, argv, "a:c:d:ln:p:r:st:u:vx:")) != EOF) { - switch(ch) { - case 'a': - add_group = True; - group=optarg; - break; - case 'c': - change_group = True; - sid=optarg; - break; - case 'd': - group_desc=optarg; - break; - case 'l': - long_list = True; - break; - case 'n': - nt_group = True; - ntgroup=optarg; - break; - case 'p': - priv = True; - privilege=optarg; - break; - case 'r': - rid = atoi(optarg); - break; - case 's': - long_list = False; - break; - case 't': - group_type = True; - groupt=optarg; - break; - case 'u': - group=optarg; - break; - case 'v': - view_group = True; - break; - case 'x': - delete_group = True; - group=optarg; - break; - /*default: - usage();*/ - } - } - - - if (((add_group?1:0) + (view_group?1:0) + (change_group?1:0) + (delete_group?1:0)) > 1) { - fprintf (stderr, "Incompatible options on command line!\n"); - usage(); - exit(1); - } - - /* no option on command line -> list groups */ - if (((add_group?1:0) + (view_group?1:0) + (change_group?1:0) + (delete_group?1:0)) == 0) - view_group = True; - - - if (group_type==False) - sid_type=SID_NAME_UNKNOWN; - else { - switch (groupt[0]) { - case 'l': - case 'L': - sid_type=SID_NAME_ALIAS; - break; - case 'd': - case 'D': - sid_type=SID_NAME_DOM_GRP; - break; - case 'b': - case 'B': - sid_type=SID_NAME_WKN_GRP; - break; - default: - sid_type=SID_NAME_UNKNOWN; - break; - } - } - - if (add_group) { - gid_t gid=nametogid(group); - if (gid==-1) { - printf("unix group %s doesn't exist!\n", group); - return -1; - } - - if (rid == -1) { - rid = pdb_gid_to_group_rid(gid); - } - return addgroup(gid, sid_type, ntgroup?ntgroup:group, - group_desc, privilege, rid); - } - - if (view_group) - return listgroup(sid_type, long_list); - - if (delete_group) - return deletegroup(group); - - if (change_group) { - return changegroup(sid, group, sid_type, ntgroup, group_desc, privilege); - } - - usage(); - - return 0; -} |