diff options
Diffstat (limited to 'source3/utils')
-rw-r--r-- | source3/utils/profiles.c | 250 |
1 files changed, 250 insertions, 0 deletions
diff --git a/source3/utils/profiles.c b/source3/utils/profiles.c new file mode 100644 index 0000000000..f14bcf8d85 --- /dev/null +++ b/source3/utils/profiles.c @@ -0,0 +1,250 @@ +#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 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", sid->sub_auths[i]); + + } + fprintf(stdout, "\n"); +} + +void print_acl(ACL *acl, char *prefix) +{ + int ace_cnt, i; + ACE *ace; + + ace_cnt = acl->num_aces; + ace = &acl->aces; + fprintf(stdout, "%sACEs: %u\n", prefix, ace_cnt); + for (i=0; i<ace_cnt; i++) { + fprintf(stdout, "%s Perms: %08X, SID: ", prefix, ace->perms); + print_sid(&ace->trustee); + ace = (ACE *)((char *)ace + ace->length); + } +} + +int main(int argc, char *argv[]) +{ + int i, fd, aces, start = 0; + void *base; + struct stat sbuf; + fstring sid_str; + 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) { + fprintf(stderr, "Usage: profiles profile-file\n"); + exit(1); + } + + fd = open(argv[1], O_RDWR, 0000); + + if (fd < 0) { + fprintf(stderr, "Could not open %s: %s\n", argv[1], + strerror(errno)); + exit(2); + } + + if (fstat(fd, &sbuf) < 0) { + fprintf(stderr, "Could not stat file %s, %s\n", argv[1], + 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_PRIVATE, fd, 0); + + if ((int)base == -1) { + fprintf(stderr, "Could not mmap file: %s, %s\n", argv[1], + strerror(errno)); + exit(4); + } + + regf_hdr = (REGF_HDR *)base; + + fprintf(stdout, "Registry file size: %u\n", sbuf.st_size); + + if (regf_hdr->REGF_ID != REG_REGF_ID) { + fprintf(stderr, "Incorrect Registry file (doesn't have header ID): %s\n", argv[1]); + exit(5); + } + + fprintf(stdout, "First Key Off: %u, Data Block Size: %u\n", + regf_hdr->first_key, regf_hdr->dblk_size); + + hbin_hdr = (HBIN_HDR *)(base + 0x1000); + + /* + * This should be the hbin_hdr + */ + + if (hbin_hdr->HBIN_ID != REG_HBIN_ID) { + fprintf(stderr, "Incorrect hbin hdr: %s\n", argv[1]); + exit(6); + } + + fprintf(stdout, "Next Off: %u, Prev Off: %u\n", + hbin_hdr->next_off, hbin_hdr->prev_off); + + nk_hdr = (NK_HDR *)(base + 0x1000 + regf_hdr->first_key + 4); + + if (nk_hdr->NK_ID != REG_NK_ID) { + fprintf(stderr, "Incorrect NK Header: %s\n", argv[1]); + exit(7); + } + + fprintf(stdout, "Type: %0x\n", nk_hdr->type); + fprintf(stdout, "SK Off : %o\n", (0x1000 + nk_hdr->sk_off + 4)); + + sk_hdr = (SK_HDR *)(base + 0x1000 + nk_hdr->sk_off + 4); + sk_off = first_sk_off = nk_hdr->sk_off; + + do { + DOM_SID *owner_sid, *group_sid; + ACL *sacl, *dacl; + if (sk_hdr->SK_ID != REG_SK_ID) { + fprintf(stderr, "Incorrect SK Header format: %08X\n", + (0x1000 + nk_hdr->sk_off + 4)); + exit(8); + } + ptr = (int *)sk_hdr; + fprintf(stdout, "Off: %08X, Refs: %u, Size: %u\n", + sk_off, sk_hdr->ref_cnt, sk_hdr->rec_size); + sec_desc = &(sk_hdr->sec_desc[0]); + owner_sid = (DOM_SID *)(&sk_hdr->sec_desc[0] + sec_desc->owner_off); + group_sid = (DOM_SID *)(&sk_hdr->sec_desc[0] + sec_desc->group_off); + sacl = (ACL *)(&sk_hdr->sec_desc[0] + sec_desc->sacl_off); + dacl = (ACL *)(&sk_hdr->sec_desc[0] + sec_desc->dacl_off); + fprintf(stdout, " Owner SID: "); print_sid(owner_sid); + fprintf(stdout, " Group SID: "); print_sid(group_sid); + fprintf(stdout, " SACL: "); + if (!sec_desc->sacl_off) + fprintf(stdout, "NONE\n"); + else + print_acl(sacl, " "); + fprintf(stdout, " DACL: "); + if (!sec_desc->dacl_off) + fprintf(stdout, "NONE\n"); + else + print_acl(dacl, " "); + sk_off = sk_hdr->prev_off; + sk_hdr = (SK_HDR *)(base + OFF(sk_hdr->prev_off)); + } while (sk_off != first_sk_off); + +} + |