Changeset 745 for trunk/server/source3/auth/auth_netlogond.c
- Timestamp:
- Nov 27, 2012, 4:43:17 PM (13 years ago)
- Location:
- trunk/server
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/server
- Property svn:mergeinfo changed
/vendor/current merged: 581,587,591,594,597,600,615,618,740
- Property svn:mergeinfo changed
-
trunk/server/source3/auth/auth_netlogond.c
r596 r745 19 19 20 20 #include "includes.h" 21 #include "auth.h" 21 22 #include "../libcli/auth/libcli_auth.h" 23 #include "../librpc/gen_ndr/ndr_netlogon.h" 24 #include "librpc/gen_ndr/ndr_schannel.h" 25 #include "rpc_client/cli_pipe.h" 26 #include "rpc_client/cli_netlogon.h" 27 #include "secrets.h" 28 #include "tldap.h" 29 #include "tldap_util.h" 22 30 23 31 #undef DBGC_CLASS 24 32 #define DBGC_CLASS DBGC_AUTH 33 34 static bool secrets_store_local_schannel_creds( 35 const struct netlogon_creds_CredentialState *creds) 36 { 37 DATA_BLOB blob; 38 enum ndr_err_code ndr_err; 39 bool ret; 40 41 ndr_err = ndr_push_struct_blob( 42 &blob, talloc_tos(), creds, 43 (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState); 44 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 45 DEBUG(10, ("ndr_push_netlogon_creds_CredentialState failed: " 46 "%s\n", ndr_errstr(ndr_err))); 47 return false; 48 } 49 ret = secrets_store(SECRETS_LOCAL_SCHANNEL_KEY, 50 blob.data, blob.length); 51 data_blob_free(&blob); 52 return ret; 53 } 54 55 static struct netlogon_creds_CredentialState * 56 secrets_fetch_local_schannel_creds(TALLOC_CTX *mem_ctx) 57 { 58 struct netlogon_creds_CredentialState *creds; 59 enum ndr_err_code ndr_err; 60 DATA_BLOB blob; 61 62 blob.data = (uint8_t *)secrets_fetch(SECRETS_LOCAL_SCHANNEL_KEY, 63 &blob.length); 64 if (blob.data == NULL) { 65 DEBUG(10, ("secrets_fetch failed\n")); 66 return NULL; 67 } 68 69 creds = talloc(mem_ctx, struct netlogon_creds_CredentialState); 70 if (creds == NULL) { 71 DEBUG(10, ("talloc failed\n")); 72 SAFE_FREE(blob.data); 73 return NULL; 74 } 75 ndr_err = ndr_pull_struct_blob( 76 &blob, creds, creds, 77 (ndr_pull_flags_fn_t)ndr_pull_netlogon_creds_CredentialState); 78 SAFE_FREE(blob.data); 79 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 80 DEBUG(10, ("ndr_pull_netlogon_creds_CredentialState failed: " 81 "%s\n", ndr_errstr(ndr_err))); 82 TALLOC_FREE(creds); 83 return NULL; 84 } 85 86 return creds; 87 } 25 88 26 89 static NTSTATUS netlogond_validate(TALLOC_CTX *mem_ctx, 27 90 const struct auth_context *auth_context, 28 91 const char *ncalrpc_sockname, 29 uint8_t schannel_key[16],30 const auth_usersupplied_info *user_info,92 struct netlogon_creds_CredentialState *creds, 93 const struct auth_usersupplied_info *user_info, 31 94 struct netr_SamInfo3 **pinfo3, 32 95 NTSTATUS *schannel_bind_result) 33 96 { 34 97 struct rpc_pipe_client *p = NULL; 35 struct cli_pipe_auth_data *auth = NULL;98 struct pipe_auth_data *auth = NULL; 36 99 struct netr_SamInfo3 *info3 = NULL; 37 100 NTSTATUS status; … … 47 110 } 48 111 49 /* 50 * We have to fake a struct dcinfo, so that 51 * rpccli_netlogon_sam_network_logon_ex can decrypt the session keys. 52 */ 53 54 p->dc = netlogon_creds_client_init_session_key(p, schannel_key); 55 if (p->dc == NULL) { 56 DEBUG(0, ("talloc failed\n")); 57 TALLOC_FREE(p); 58 return NT_STATUS_NO_MEMORY; 59 } 112 p->dc = creds; 60 113 61 114 status = rpccli_schannel_bind_data(p, lp_workgroup(), … … 79 132 status = rpccli_netlogon_sam_network_logon_ex( 80 133 p, p, 81 user_info->logon_parameters, /* flags such as 'allow82 * workstation logon' */83 global_myname(), /* server name */84 user_info-> smb_name, /* user name logging on. */85 user_info->client _domain,/* domain name */86 user_info->w ksta_name,/* workstation name */134 user_info->logon_parameters, /* flags such as 'allow 135 * workstation logon' */ 136 global_myname(), /* server name */ 137 user_info->client.account_name, /* user name logging on. */ 138 user_info->client.domain_name, /* domain name */ 139 user_info->workstation_name, /* workstation name */ 87 140 (uchar *)auth_context->challenge.data, /* 8 byte challenge. */ 88 3, 89 user_info-> lm_resp,/* lanman 24 byte response */90 user_info-> nt_resp,/* nt 24 byte response */91 &info3); /* info3 out */141 3, /* validation level */ 142 user_info->password.response.lanman, /* lanman 24 byte response */ 143 user_info->password.response.nt, /* nt 24 byte response */ 144 &info3); /* info3 out */ 92 145 93 146 DEBUG(10, ("rpccli_netlogon_sam_network_logon_ex returned %s\n", … … 105 158 } 106 159 107 static char *mymachinepw(TALLOC_CTX *mem_ctx) 108 { 109 fstring pwd; 110 const char *script; 111 char *to_free = NULL; 112 ssize_t nread; 113 int ret, fd; 114 115 script = lp_parm_const_string( 116 GLOBAL_SECTION_SNUM, "auth_netlogond", "machinepwscript", 117 NULL); 118 119 if (script == NULL) { 120 to_free = talloc_asprintf(talloc_tos(), "%s/%s", 121 get_dyn_SBINDIR(), "mymachinepw"); 122 script = to_free; 123 } 124 if (script == NULL) { 125 return NULL; 126 } 127 128 ret = smbrun(script, &fd); 129 DEBUG(ret ? 0 : 3, ("mymachinepw: Running the command `%s' gave %d\n", 130 script, ret)); 131 TALLOC_FREE(to_free); 132 133 if (ret != 0) { 134 return NULL; 135 } 136 137 nread = read(fd, pwd, sizeof(pwd)-1); 138 close(fd); 139 140 if (nread <= 0) { 141 DEBUG(3, ("mymachinepwd: Could not read password\n")); 142 return NULL; 143 } 144 145 pwd[nread] = '\0'; 146 147 if (pwd[nread-1] == '\n') { 148 pwd[nread-1] = '\0'; 149 } 150 151 return talloc_strdup(mem_ctx, pwd); 160 static NTSTATUS get_ldapi_ctx(TALLOC_CTX *mem_ctx, struct tldap_context **pld) 161 { 162 struct tldap_context *ld; 163 struct sockaddr_un addr; 164 char *sockaddr; 165 int fd; 166 NTSTATUS status; 167 int res; 168 169 sockaddr = talloc_asprintf(talloc_tos(), "/%s/ldap_priv/ldapi", 170 lp_private_dir()); 171 if (sockaddr == NULL) { 172 DEBUG(10, ("talloc failed\n")); 173 return NT_STATUS_NO_MEMORY; 174 } 175 176 ZERO_STRUCT(addr); 177 addr.sun_family = AF_UNIX; 178 strncpy(addr.sun_path, sockaddr, sizeof(addr.sun_path)); 179 TALLOC_FREE(sockaddr); 180 181 status = open_socket_out((struct sockaddr_storage *)(void *)&addr, 182 0, 0, &fd); 183 if (!NT_STATUS_IS_OK(status)) { 184 DEBUG(10, ("Could not connect to %s: %s\n", addr.sun_path, 185 nt_errstr(status))); 186 return status; 187 } 188 set_blocking(fd, false); 189 190 ld = tldap_context_create(mem_ctx, fd); 191 if (ld == NULL) { 192 close(fd); 193 return NT_STATUS_NO_MEMORY; 194 } 195 res = tldap_fetch_rootdse(ld); 196 if (res != TLDAP_SUCCESS) { 197 DEBUG(10, ("tldap_fetch_rootdse failed: %s\n", 198 tldap_errstr(talloc_tos(), ld, res))); 199 TALLOC_FREE(ld); 200 return NT_STATUS_LDAP(res); 201 } 202 *pld = ld; 203 return NT_STATUS_OK;; 204 } 205 206 static NTSTATUS mymachinepw(uint8_t pwd[16]) 207 { 208 TALLOC_CTX *frame = talloc_stackframe(); 209 struct tldap_context *ld = NULL; 210 struct tldap_message *rootdse, **msg; 211 const char *attrs[1] = { "unicodePwd" }; 212 char *default_nc, *myname; 213 int rc, num_msg; 214 DATA_BLOB pwdblob; 215 NTSTATUS status; 216 217 status = get_ldapi_ctx(talloc_tos(), &ld); 218 if (!NT_STATUS_IS_OK(status)) { 219 goto fail; 220 } 221 rootdse = tldap_rootdse(ld); 222 if (rootdse == NULL) { 223 DEBUG(10, ("Could not get rootdse\n")); 224 status = NT_STATUS_INTERNAL_ERROR; 225 goto fail; 226 } 227 default_nc = tldap_talloc_single_attribute( 228 rootdse, "defaultNamingContext", talloc_tos()); 229 if (default_nc == NULL) { 230 DEBUG(10, ("Could not get defaultNamingContext\n")); 231 status = NT_STATUS_NO_MEMORY; 232 goto fail; 233 } 234 DEBUG(10, ("default_nc = %s\n", default_nc)); 235 236 myname = talloc_asprintf_strupper_m(talloc_tos(), "%s$", 237 global_myname()); 238 if (myname == NULL) { 239 DEBUG(10, ("talloc failed\n")); 240 status = NT_STATUS_NO_MEMORY; 241 goto fail; 242 } 243 244 rc = tldap_search_fmt( 245 ld, default_nc, TLDAP_SCOPE_SUB, attrs, ARRAY_SIZE(attrs), 0, 246 talloc_tos(), &msg, 247 "(&(sAMAccountName=%s)(objectClass=computer))", myname); 248 if (rc != TLDAP_SUCCESS) { 249 DEBUG(10, ("Could not retrieve our account: %s\n", 250 tldap_errstr(talloc_tos(), ld, rc))); 251 status = NT_STATUS_LDAP(rc); 252 goto fail; 253 } 254 num_msg = talloc_array_length(msg); 255 if (num_msg != 1) { 256 DEBUG(10, ("Got %d accounts, expected one\n", num_msg)); 257 status = NT_STATUS_INTERNAL_DB_CORRUPTION; 258 goto fail; 259 } 260 if (!tldap_get_single_valueblob(msg[0], "unicodePwd", &pwdblob)) { 261 char *dn = NULL; 262 tldap_entry_dn(msg[0], &dn); 263 DEBUG(10, ("No unicodePwd attribute in %s\n", 264 dn ? dn : "<unknown DN>")); 265 status = NT_STATUS_INTERNAL_DB_CORRUPTION; 266 goto fail; 267 } 268 if (pwdblob.length != 16) { 269 DEBUG(10, ("Password hash hash has length %d, expected 16\n", 270 (int)pwdblob.length)); 271 status = NT_STATUS_INTERNAL_DB_CORRUPTION; 272 goto fail; 273 } 274 memcpy(pwd, pwdblob.data, 16); 275 276 fail: 277 TALLOC_FREE(frame); 278 return status; 152 279 } 153 280 … … 155 282 void *my_private_data, 156 283 TALLOC_CTX *mem_ctx, 157 const auth_usersupplied_info *user_info,158 auth_serversupplied_info **server_info)284 const struct auth_usersupplied_info *user_info, 285 struct auth_serversupplied_info **server_info) 159 286 { 160 287 TALLOC_CTX *frame = talloc_stackframe(); 161 288 struct netr_SamInfo3 *info3 = NULL; 162 289 struct rpc_pipe_client *p = NULL; 163 struct cli_pipe_auth_data *auth = NULL;290 struct pipe_auth_data *auth = NULL; 164 291 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; 165 char *plaintext_machinepw = NULL;166 292 uint8_t machine_password[16]; 167 uint8_t schannel_key[16];293 struct netlogon_creds_CredentialState *creds; 168 294 NTSTATUS schannel_bind_result, status; 169 295 struct named_mutex *mutex = NULL; 170 296 const char *ncalrpcsock; 171 297 298 DEBUG(10, ("Check auth for: [%s]\n", user_info->mapped.account_name)); 299 172 300 ncalrpcsock = lp_parm_const_string( 173 301 GLOBAL_SECTION_SNUM, "auth_netlogond", "socket", NULL); … … 183 311 } 184 312 185 if (!secrets_fetch_local_schannel_key(schannel_key)) { 313 creds = secrets_fetch_local_schannel_creds(talloc_tos()); 314 if (creds == NULL) { 186 315 goto new_key; 187 316 } 188 317 189 318 status = netlogond_validate(talloc_tos(), auth_context, ncalrpcsock, 190 schannel_key, user_info, &info3,319 creds, user_info, &info3, 191 320 &schannel_bind_result); 192 321 … … 237 366 } 238 367 239 plaintext_machinepw = mymachinepw(talloc_tos()); 240 if (plaintext_machinepw == NULL) { 241 status = NT_STATUS_NO_MEMORY; 242 goto done; 243 } 244 245 E_md4hash(plaintext_machinepw, machine_password); 246 247 TALLOC_FREE(plaintext_machinepw); 368 status = mymachinepw(machine_password); 369 if (!NT_STATUS_IS_OK(status)) { 370 DEBUG(10, ("mymachinepw failed: %s\n", nt_errstr(status))); 371 goto done; 372 } 373 374 DEBUG(10, ("machinepw ")); 375 dump_data(10, machine_password, 16); 248 376 249 377 status = rpccli_netlogon_setup_creds( … … 257 385 } 258 386 259 memcpy(schannel_key, p->dc->session_key, 16); 260 secrets_store_local_schannel_key(schannel_key); 261 262 TALLOC_FREE(p); 387 secrets_store_local_schannel_creds(p->dc); 263 388 264 389 /* … … 268 393 269 394 status = netlogond_validate(talloc_tos(), auth_context, ncalrpcsock, 270 schannel_key, user_info, &info3,395 p->dc, user_info, &info3, 271 396 &schannel_bind_result); 272 397 398 TALLOC_FREE(p); 399 273 400 DEBUG(10, ("netlogond_validate returned %s\n", nt_errstr(status))); 274 401 … … 279 406 okay: 280 407 281 status = make_server_info_info3(mem_ctx, user_info-> smb_name,282 user_info-> domain, server_info,408 status = make_server_info_info3(mem_ctx, user_info->client.account_name, 409 user_info->mapped.domain_name, server_info, 283 410 info3); 284 411 if (!NT_STATUS_IS_OK(status)) { … … 301 428 auth_methods **auth_method) 302 429 { 303 if (!make_auth_methods(auth_context, auth_method)) { 430 struct auth_methods *result; 431 432 result = TALLOC_ZERO_P(auth_context, struct auth_methods); 433 if (result == NULL) { 304 434 return NT_STATUS_NO_MEMORY; 305 435 } 306 307 (*auth_method)->name = "netlogond"; 308 (*auth_method)->auth = check_netlogond_security; 436 result->name = "netlogond"; 437 result->auth = check_netlogond_security; 438 439 *auth_method = result; 309 440 return NT_STATUS_OK; 310 441 }
Note:
See TracChangeset
for help on using the changeset viewer.