1 /* 2 * sam.h - known structures in the SAM hive of NT registry 3 * 4 ***** 5 * 6 * NTREG - Window registry file reader / writer library 7 * Copyright (c) 1997-2012 Petter Nordahl-Hagen. 8 * 9 * This library is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU Lesser General Public 11 * License as published by the Free Software Foundation; 12 * version 2.1 of the License. 13 * 14 * This library is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * Lesser General Public License for more details. 18 * See file LGPL.txt for the full license. 19 * 20 */ 21 22 #ifndef _INCLUDE_SAM_H 23 #define _INCLUDE_SAM_H 1 24 25 #include <sys/types.h> 26 #include <inttypes.h> 27 28 29 /* Account V, contains machine SID and a lot of unknonw stuff */ 30 31 #define SID_BIN_LEN 24 /* Lenght of binary machine SID, incl header */ 32 #define SID_STR_MAX 50 /* Max string lenght of S-1-5-xxx-xxx-xxx-xxx type SID */ 33 34 #define ACCOUNTDB_V_PATH "\\SAM\\Domains\\Account\\V" 35 36 struct accountdb_V { 37 char unknown1[0x38]; /* No idea what it does */ 38 uint32_t sid_ofs; /* 38 - Offset to machine SID */ 39 uint32_t sid_len; /* 3c - Lenght of sid (should be 0x14?) */ 40 // char unknown2[0x4]; /* 40 */ 41 /* Data start at 0x40 ?? */ 42 char data[4]; 43 }; 44 45 /* This contains some policy settings for the account database */ 46 47 #define ACCOUNTDB_F_PATH "\\SAM\\Domains\\Account\\F" 48 49 50 struct accountdb_F { 51 char unknown1[8]; /* 0 */ 52 char unknown2[8]; /* 8 */ 53 uint32_t updatecnt; /* 10 Number of times policy data updated */ 54 char unknown3[4]; /* 14 */ 55 char t_maxpwage[8]; /* 18 Maximum password age, GUI shows only days */ 56 char t_minpwage[8]; /* 20 Minimum password age, GUI shows only days */ 57 char unknown4[8]; /* 28 */ 58 char t_lockdur[8]; /* 30 Account lockout duration, GUI shows minutes */ 59 char t_lockrel[8]; /* 38 Release account lockout after, GUI show minutes */ 60 char unknown5[8]; /* 40 */ 61 uint32_t rid; /* 48 RID of user doing last edit? */ 62 uint32_t flags; /* 4c Some flags & options, see below */ 63 unsigned short minpwlen; /* 50 Minimum password lenght */ 64 unsigned short numhist; /* 52 How many passwords to keep in history */ 65 unsigned short locklimit; /*54 How many tries before lockout */ 66 char unknown6[0x9a]; /* Rest is unknown */ 67 }; /* Total size 0xF0 bytes, seems to be constant */ 68 69 /* Known bits in flags field */ 70 71 #define ACF_COMPLEX 0x0001 /* Pass must meet complexity req. */ 72 #define ACF_REVERSIBLE 0x0010 /* Store password using reversible encryption */ 73 74 75 /* This is users F value, contains account type & state etc */ 76 77 #define USER_F_PATH "\\SAM\\Domains\\Account\\Users\\%08X\\F" 78 79 struct user_F { 80 char unknown1[8]; 81 char t_lockout[8]; /* Time of lockout */ 82 char unknown2[8]; 83 char t_creation[8]; /* Time of account creation */ 84 char unknown3[8]; 85 char t_login[8]; /* Time of last login */ 86 int32_t rid; 87 char unknown4[4]; 88 unsigned short ACB_bits; /* Account type and status flags */ 89 char unknown5[6]; 90 unsigned short failedcnt; /* Count of failed logins, if > than policy it is locked */ 91 unsigned short logins; /* Total logins since creation */ 92 char unknown6 [0xc]; 93 }; 94 95 #define ACB_DISABLED 0x0001 /* Act disabled */ 96 #define ACB_HOMDIRREQ 0x0002 /* Home directory required */ 97 #define ACB_PWNOTREQ 0x0004 /* User password not req */ 98 #define ACB_TEMPDUP 0x0008 /* Temporary duplicate account?? */ 99 #define ACB_NORMAL 0x0010 /* Normal user account */ 100 #define ACB_MNS 0x0020 /* MNS logon user account */ 101 #define ACB_DOMTRUST 0x0040 /* Interdomain trust account */ 102 #define ACB_WSTRUST 0x0080 /* Workstation trust account */ 103 104 #define ACB_SVRTRUST 0x0100 /* Server trust account */ 105 #define ACB_PWNOEXP 0x0200 /* User password does not expire */ 106 /* Seems not to be used on failed console logins at least */ 107 #define ACB_AUTOLOCK 0x0400 /* Account auto locked */ 108 109 /* Account Bits Fields strings (defined in libsam.c) 110 111 char *acb_fields[16] = { 112 "Disabled" , 113 "Homedir req." , 114 "Passwd not req." , 115 "Temp. duplicate" , 116 "Normal account" , 117 "NMS account" , 118 "Domain trust act." , 119 "Wks trust act." , 120 "Srv trust act" , 121 "Pwd don't expire" , 122 "Auto lockout" , 123 "(unknown 0x08)" , 124 "(unknown 0x10)" , 125 "(unknown 0x20)" , 126 "(unknown 0x40)" , 127 "(unknown 0x80)" , 128 }; 129 130 */ 131 132 133 /* Users V data struct */ 134 /* First 0xCC bytes is pointer & len table, rest is data which 135 * the table points to 136 * String data is unicode, not zero terminated (must use len) 137 */ 138 139 struct user_V { 140 141 int unknown1_1; /* 0x00 - always zero? */ 142 int unknown1_2; /* 0x04 - points to username? */ 143 int unknown1_3; /* 0x08 - always 0x02 0x00 0x01 0x00 ? */ 144 145 int username_ofs; /* 0x0c */ 146 int username_len; /* 0x10 */ 147 148 int unknown2_1; /* 0x14 - always zero? */ 149 150 int fullname_ofs; /* 0x18 */ 151 int fullname_len; /* 0x1c */ 152 153 int unknown3_1; /* 0x20 - always zero? */ 154 155 int comment_ofs; /* 0x24 */ 156 int comment_len; /* 0x28 */ 157 158 int unknown4_1; /* 0x2c - alway zero? */ 159 int unknown4_2; /* 0x30 - points 4 or 8 byte field before hashes */ 160 int unknown4_3; /* 0x34 - zero? or size? */ 161 int unknown4_4; /* 0x38 - zero? */ 162 int unknown4_5; /* 0x3c - to field 8 bytes before hashes */ 163 int unknown4_6; /* 0x40 - zero? or size of above? */ 164 int unknown4_7; /* 0x44 - zero? */ 165 166 int homedir_ofs; /* 0x48 */ 167 int homedir_len; /* 0x4c */ 168 169 int unknown5_1; /* 0x50 - zero? */ 170 171 int drvletter_ofs; /* 0x54 - drive letter for home dir */ 172 int drvletter_len; /* 0x58 - len of above, usually 4 */ 173 174 int unknown6_1; /* 0x5c - zero? */ 175 176 int logonscr_ofs; /* 0x60 - users logon script path */ 177 int logonscr_len; /* 0x64 - length of string */ 178 179 int unknown7_1; /* 0x68 - zero? */ 180 181 int profilep_ofs; /* 0x6c - profile path string */ 182 int profilep_len; /* 0x70 - profile path stringlen */ 183 184 char unknown7[0x90-0x74]; /* 0x74 */ 185 186 int unknown8_1; /* 0x90 - pointer to some place before hashes, after comments */ 187 int unknown8_2; /* 0x94 - size of above? */ 188 int unknown8_3; /* 0x98 - unknown? always 1? */ 189 190 int lmpw_ofs; /* 0x9c */ 191 int lmpw_len; /* 0xa0 */ 192 193 int unknown9_1; /* 0xa4 - zero? */ 194 195 int ntpw_ofs; /* 0xa8 */ 196 int ntpw_len; /* 0xac */ 197 198 int unknowna_1; /* 0xb0 */ 199 int unknowna_2; /* 0xb4 - points to field after hashes */ 200 int unknowna_3; /* 0xb8 - size of above field */ 201 int unknowna_4; /* 0xbc - zero? */ 202 int unknowna_5; /* 0xc0 - points to field after that */ 203 int unknowna_6; /* 0xc4 - size of above */ 204 int unknowna_7; /* 0xc8 - zero ? */ 205 206 char data[4]; /* Data starts here. All pointers above is relative to this, 207 that is V + 0xCC */ 208 209 }; 210 211 /* Groups C data struct 212 * First 0x34 bytes is pointer & len table, rest is data which 213 * the table points to 214 * String data is unicode, not zero terminated (must use len) 215 */ 216 217 struct group_C { 218 219 int groupid; /* 0x00 - Seems to be the group ID */ 220 int unknown1_1; /* 0x04 - always zero? */ 221 int unknown1_2; /* 0x08 - points to groupname? */ 222 int unknown1_3; /* 0x0c - always 0x02 0x00 0x01 0x00 ? */ 223 224 int grpname_ofs; /* 0x10 */ 225 int grpname_len; /* 0x14 */ 226 227 int unknown2_1; /* 0x18 - always zero? */ 228 229 int fullname_ofs; /* 0x1c */ 230 int fullname_len; /* 0x20 */ 231 232 int unknown3_1; /* 0x24 - always zero? */ 233 234 int members_ofs; /* 0x28 - offset to member list, which is SIDs */ 235 int members_len; /* 0x2c - member list size */ 236 237 int grp_members; /* 0x30 - number of group members */ 238 239 /* 0x34 - data starts here. pointers above are offset from this */ 240 241 char data[]; 242 243 }; 244 245 /* Variable length binary structure that most SIDs are stored in 246 */ 247 248 struct sid_binary { 249 uint8_t revision; /* 0x0 - Don't know. Always 1? Revision level? number of SIDs following? */ 250 uint8_t sections; /* 0x1 - Number of parts, 4 bytes each (unsigne integer) */ 251 uint8_t unknown2; /* 0x2 - Unknown, seems to be null padding */ 252 uint8_t unknown3; /* 0x3 - Unknown, seems to be null padding */ 253 254 uint8_t unknown4; /* 0x4 - Unknown */ 255 uint8_t unknown5; /* 0x5 - Unknown */ 256 uint8_t unknown6; /* 0x6 - Unknown */ 257 uint8_t authority; /* 0x7 - Unknown, often 5 (could this be 8bit authority number?) */ 258 259 260 uint32_t array[8]; /* As many as sections value says it is */ 261 }; 262 263 /* Array of SIDs */ 264 265 struct sid_array { 266 int len; 267 struct sid_binary *sidptr; 268 }; 269 270 271 /* libsam.c functions */ 272 273 int sam_get_lockoutinfo(struct hive *hdesc, int show); 274 short sam_handle_accountbits(struct hive *hdesc, int rid, int mode); 275 int sam_get_machine_sid(struct hive *hdesc, char *sidbuf); 276 char *sam_sid_to_string(struct sid_binary *sidbuf); 277 struct sid_array *sam_make_sid_array(struct sid_binary *sidbuf, int size); 278 void sam_free_sid_array(struct sid_array *array); 279 int sam_sid_cmp(struct sid_binary *s1, struct sid_binary *s2); 280 int sam_get_grp_members_sid(struct hive *hdesc, int grp, struct sid_array **sarray); 281 int sam_put_grp_members_sid(struct hive *hdesc, int grp, struct sid_array *sarray); 282 struct keyval *sam_get_user_grpids(struct hive *hdesc, int rid); 283 int sam_put_user_grpids(struct hive *hdesc, int rid, struct keyval *val); 284 int sam_add_user_to_grp(struct hive *hdesc, int rid, int grp); 285 int sam_remove_user_from_grp(struct hive *hdesc, int rid, int grp); 286 char *sam_get_username(struct hive *hdesc, int rid); 287 char *sam_get_groupname(struct hive *hdesc, int grpid); 288 int sam_list_users(struct hive *hdesc, int readable); 289 int sam_list_user_groups(struct hive *hdesc, int rid, int check); 290 int sam_reset_pw(struct hive *hdesc, int rid); 291 void sam_list_groups(struct hive *hdesc, int listmembers, int human); 292 int sam_reset_all_pw(struct hive *hdesc, int list); 293 294 295 296 #endif 297