Print this page
1575 untangle libmlrpc ... pre2:
Get rid of ndr_rpc_server_{info,os}
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/smbsrv/libmlsvc/common/netr_auth.c
+++ new/usr/src/lib/smbsrv/libmlsvc/common/netr_auth.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
25 25 */
26 26
27 27 /*
28 28 * NETR challenge/response client functions.
29 29 *
30 30 * NT_STATUS_INVALID_PARAMETER
31 31 * NT_STATUS_NO_TRUST_SAM_ACCOUNT
32 32 * NT_STATUS_ACCESS_DENIED
33 33 */
34 34
35 35 #include <stdio.h>
36 36 #include <stdlib.h>
37 37 #include <strings.h>
38 38 #include <unistd.h>
39 39 #include <ctype.h>
40 40 #include <security/cryptoki.h>
41 41 #include <security/pkcs11.h>
42 42
43 43 #include <smbsrv/libsmb.h>
44 44 #include <smbsrv/libsmbns.h>
45 45 #include <smbsrv/libmlsvc.h>
46 46 #include <smbsrv/ndl/netlogon.ndl>
47 47 #include <smbsrv/smbinfo.h>
48 48 #include <smbsrv/netrauth.h>
49 49
50 50 #define NETR_SESSKEY_ZEROBUF_SZ 4
51 51 /* The DES algorithm uses a 56-bit encryption key. */
52 52 #define NETR_DESKEY_LEN 7
53 53
54 54 int netr_setup_authenticator(netr_info_t *, struct netr_authenticator *,
55 55 struct netr_authenticator *);
56 56 DWORD netr_validate_chain(netr_info_t *, struct netr_authenticator *);
57 57
58 58 static int netr_server_req_challenge(mlsvc_handle_t *, netr_info_t *);
59 59 static int netr_server_authenticate2(mlsvc_handle_t *, netr_info_t *);
60 60 static int netr_gen_password(BYTE *, BYTE *, BYTE *);
61 61
62 62 /*
63 63 * Shared with netr_logon.c
64 64 */
65 65 netr_info_t netr_global_info;
66 66
67 67 /*
68 68 * netlogon_auth
69 69 *
70 70 * This is the core of the NETLOGON authentication protocol.
71 71 * Do the challenge response authentication.
72 72 *
73 73 * Prior to calling this function, an anonymous session to the NETLOGON
74 74 * pipe on a domain controller(server) should have already been opened.
75 75 *
76 76 * Upon a successful NETLOGON credential chain establishment, the
77 77 * netlogon sequence number will be set to match the kpasswd sequence
78 78 * number.
79 79 *
80 80 */
81 81 DWORD
82 82 netlogon_auth(char *server, mlsvc_handle_t *netr_handle, DWORD flags)
83 83 {
84 84 netr_info_t *netr_info;
85 85 int rc;
86 86 DWORD leout_rc[2];
87 87
88 88 netr_info = &netr_global_info;
89 89 bzero(netr_info, sizeof (netr_info_t));
90 90
91 91 netr_info->flags |= flags;
92 92
93 93 rc = smb_getnetbiosname(netr_info->hostname, NETBIOS_NAME_SZ);
94 94 if (rc != 0)
95 95 return (NT_STATUS_UNSUCCESSFUL);
96 96
97 97 /* server is our DC. Note: normally an FQDN. */
98 98 (void) snprintf(netr_info->server, sizeof (netr_info->server),
99 99 "\\\\%s", server);
100 100
101 101 LE_OUT32(&leout_rc[0], random());
102 102 LE_OUT32(&leout_rc[1], random());
103 103 (void) memcpy(&netr_info->client_challenge, leout_rc,
104 104 sizeof (struct netr_credential));
105 105
106 106 if ((rc = netr_server_req_challenge(netr_handle, netr_info)) == 0) {
107 107 rc = netr_server_authenticate2(netr_handle, netr_info);
108 108 if (rc == 0) {
109 109 /*
110 110 * TODO: (later) When joining a domain using a
111 111 * pre-created machine account, should do:
112 112 * netr_server_password_set(&netr_handle, netr_info);
113 113 * Nexenta issue 11960
114 114 */
115 115 smb_update_netlogon_seqnum();
116 116 netr_info->flags |= NETR_FLG_VALID;
117 117
118 118 }
119 119 }
120 120
121 121 return ((rc) ? NT_STATUS_UNSUCCESSFUL : NT_STATUS_SUCCESS);
122 122 }
123 123
124 124 /*
125 125 * netr_open
126 126 *
127 127 * Open an anonymous session to the NETLOGON pipe on a domain controller
128 128 * and bind to the NETR RPC interface.
129 129 *
130 130 * We store the remote server information, which is used to drive Windows
131 131 * version specific behavior.
132 132 *
133 133 * Returns 0 or NT status
134 134 */
135 135 DWORD
136 136 netr_open(char *server, char *domain, mlsvc_handle_t *netr_handle)
137 137 {
138 138 char user[SMB_USERNAME_MAXLEN];
139 139 DWORD status;
140 140
141 141 smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
142 142
143 143 status = ndr_rpc_bind(netr_handle, server, domain, user, "NETR");
144 144
145 145 return (status);
146 146 }
147 147
148 148 /*
149 149 * netr_close
150 150 *
151 151 * Close a NETLOGON pipe and free the RPC context.
152 152 */
153 153 int
154 154 netr_close(mlsvc_handle_t *netr_handle)
155 155 {
156 156 ndr_rpc_unbind(netr_handle);
157 157 return (0);
158 158 }
159 159
160 160 /*
161 161 * netr_server_req_challenge
162 162 */
163 163 static int
164 164 netr_server_req_challenge(mlsvc_handle_t *netr_handle, netr_info_t *netr_info)
165 165 {
166 166 struct netr_ServerReqChallenge arg;
167 167 int opnum;
168 168
169 169 bzero(&arg, sizeof (struct netr_ServerReqChallenge));
170 170 opnum = NETR_OPNUM_ServerReqChallenge;
171 171
172 172 arg.servername = (unsigned char *)netr_info->server;
173 173 arg.hostname = (unsigned char *)netr_info->hostname;
174 174
175 175 (void) memcpy(&arg.client_challenge, &netr_info->client_challenge,
176 176 sizeof (struct netr_credential));
177 177
178 178 if (ndr_rpc_call(netr_handle, opnum, &arg) != 0)
179 179 return (-1);
180 180
181 181 if (arg.status != 0) {
182 182 ndr_rpc_status(netr_handle, opnum, arg.status);
183 183 ndr_rpc_release(netr_handle);
↓ open down ↓ |
183 lines elided |
↑ open up ↑ |
184 184 return (-1);
185 185 }
186 186
187 187 (void) memcpy(&netr_info->server_challenge, &arg.server_challenge,
188 188 sizeof (struct netr_credential));
189 189
190 190 ndr_rpc_release(netr_handle);
191 191 return (0);
192 192 }
193 193
194 +uint32_t netr_server_auth2_flags =
195 + NETR_NEGOTIATE_BASE_FLAGS |
196 + NETR_NEGOTIATE_STRONGKEY_FLAG;
197 +
194 198 /*
195 199 * netr_server_authenticate2
196 200 */
197 201 static int
198 202 netr_server_authenticate2(mlsvc_handle_t *netr_handle, netr_info_t *netr_info)
199 203 {
200 204 struct netr_ServerAuthenticate2 arg;
201 205 /* sizeof netr_info->hostname, + 1 for the '$' */
202 206 char account_name[(NETBIOS_NAME_SZ * 2) + 1];
203 207 int opnum;
204 208 int rc;
205 209
206 210 bzero(&arg, sizeof (struct netr_ServerAuthenticate2));
207 211 opnum = NETR_OPNUM_ServerAuthenticate2;
208 212
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
209 213 (void) snprintf(account_name, sizeof (account_name), "%s$",
210 214 netr_info->hostname);
211 215
212 216 smb_tracef("server=[%s] account_name=[%s] hostname=[%s]\n",
213 217 netr_info->server, account_name, netr_info->hostname);
214 218
215 219 arg.servername = (unsigned char *)netr_info->server;
216 220 arg.account_name = (unsigned char *)account_name;
217 221 arg.account_type = NETR_WKSTA_TRUST_ACCOUNT_TYPE;
218 222 arg.hostname = (unsigned char *)netr_info->hostname;
219 - arg.negotiate_flags = NETR_NEGOTIATE_BASE_FLAGS;
223 + arg.negotiate_flags = netr_server_auth2_flags;
220 224
221 - if (ndr_rpc_server_os(netr_handle) == NATIVE_OS_WIN2000) {
222 - arg.negotiate_flags |= NETR_NEGOTIATE_STRONGKEY_FLAG;
225 + if (arg.negotiate_flags & NETR_NEGOTIATE_STRONGKEY_FLAG) {
223 226 if (netr_gen_skey128(netr_info) != SMBAUTH_SUCCESS)
224 227 return (-1);
225 228 } else {
226 229 if (netr_gen_skey64(netr_info) != SMBAUTH_SUCCESS)
227 230 return (-1);
228 231 }
229 232
230 233 if (netr_gen_credentials(netr_info->session_key.key,
231 234 &netr_info->client_challenge, 0,
232 235 &netr_info->client_credential) != SMBAUTH_SUCCESS) {
233 236 return (-1);
234 237 }
235 238
236 239 if (netr_gen_credentials(netr_info->session_key.key,
237 240 &netr_info->server_challenge, 0,
238 241 &netr_info->server_credential) != SMBAUTH_SUCCESS) {
239 242 return (-1);
240 243 }
241 244
242 245 (void) memcpy(&arg.client_credential, &netr_info->client_credential,
243 246 sizeof (struct netr_credential));
244 247
245 248 if (ndr_rpc_call(netr_handle, opnum, &arg) != 0)
246 249 return (-1);
247 250
248 251 if (arg.status != 0) {
249 252 ndr_rpc_status(netr_handle, opnum, arg.status);
250 253 ndr_rpc_release(netr_handle);
251 254 return (-1);
252 255 }
253 256
254 257 rc = memcmp(&netr_info->server_credential, &arg.server_credential,
255 258 sizeof (struct netr_credential));
256 259
257 260 ndr_rpc_release(netr_handle);
258 261 return (rc);
259 262 }
260 263
261 264 /*
262 265 * netr_gen_skey128
263 266 *
264 267 * Generate a 128-bit session key from the client and server challenges.
265 268 * See "Session-Key Computation" section of MS-NRPC document.
266 269 */
267 270 int
268 271 netr_gen_skey128(netr_info_t *netr_info)
269 272 {
270 273 unsigned char ntlmhash[SMBAUTH_HASH_SZ];
271 274 int rc = SMBAUTH_FAILURE;
272 275 CK_RV rv;
273 276 CK_MECHANISM mechanism;
274 277 CK_SESSION_HANDLE hSession;
275 278 CK_ULONG diglen = MD_DIGEST_LEN;
276 279 unsigned char md5digest[MD_DIGEST_LEN];
277 280 unsigned char zerobuf[NETR_SESSKEY_ZEROBUF_SZ];
278 281
279 282 bzero(ntlmhash, SMBAUTH_HASH_SZ);
280 283 /*
281 284 * We should check (netr_info->flags & NETR_FLG_INIT) and use
282 285 * the appropriate password but it isn't working yet. So we
283 286 * always use the default one for now.
284 287 */
285 288 bzero(netr_info->password, sizeof (netr_info->password));
286 289 rc = smb_config_getstr(SMB_CI_MACHINE_PASSWD,
287 290 (char *)netr_info->password, sizeof (netr_info->password));
288 291
289 292 if ((rc != SMBD_SMF_OK) || *netr_info->password == '\0') {
290 293 return (SMBAUTH_FAILURE);
291 294 }
292 295
293 296 rc = smb_auth_ntlm_hash((char *)netr_info->password, ntlmhash);
294 297 if (rc != SMBAUTH_SUCCESS)
295 298 return (SMBAUTH_FAILURE);
296 299
297 300 bzero(zerobuf, NETR_SESSKEY_ZEROBUF_SZ);
298 301
299 302 mechanism.mechanism = CKM_MD5;
300 303 mechanism.pParameter = 0;
301 304 mechanism.ulParameterLen = 0;
302 305
303 306 rv = SUNW_C_GetMechSession(mechanism.mechanism, &hSession);
304 307 if (rv != CKR_OK)
305 308 return (SMBAUTH_FAILURE);
306 309
307 310 rv = C_DigestInit(hSession, &mechanism);
308 311 if (rv != CKR_OK)
309 312 goto cleanup;
310 313
311 314 rv = C_DigestUpdate(hSession, (CK_BYTE_PTR)zerobuf,
312 315 NETR_SESSKEY_ZEROBUF_SZ);
313 316 if (rv != CKR_OK)
314 317 goto cleanup;
315 318
316 319 rv = C_DigestUpdate(hSession,
317 320 (CK_BYTE_PTR)netr_info->client_challenge.data, NETR_CRED_DATA_SZ);
318 321 if (rv != CKR_OK)
319 322 goto cleanup;
320 323
321 324 rv = C_DigestUpdate(hSession,
322 325 (CK_BYTE_PTR)netr_info->server_challenge.data, NETR_CRED_DATA_SZ);
323 326 if (rv != CKR_OK)
324 327 goto cleanup;
325 328
326 329 rv = C_DigestFinal(hSession, (CK_BYTE_PTR)md5digest, &diglen);
327 330 if (rv != CKR_OK)
328 331 goto cleanup;
329 332
330 333 rc = smb_auth_hmac_md5(md5digest, diglen, ntlmhash, SMBAUTH_HASH_SZ,
331 334 netr_info->session_key.key);
332 335
333 336 netr_info->session_key.len = NETR_SESSKEY128_SZ;
334 337 cleanup:
335 338 (void) C_CloseSession(hSession);
336 339 return (rc);
337 340
338 341 }
339 342 /*
340 343 * netr_gen_skey64
341 344 *
342 345 * Generate a 64-bit session key from the client and server challenges.
343 346 * See "Session-Key Computation" section of MS-NRPC document.
344 347 *
345 348 * The algorithm is a two stage hash. For the first hash, the input is
346 349 * the combination of the client and server challenges, the key is
347 350 * the first 7 bytes of the password. The initial password is formed
348 351 * using the NT password hash on the local hostname in lower case.
349 352 * The result is stored in a temporary buffer.
350 353 *
351 354 * input: challenge
352 355 * key: passwd lower 7 bytes
353 356 * output: intermediate result
354 357 *
355 358 * For the second hash, the input is the result of the first hash and
356 359 * the key is the last 7 bytes of the password.
357 360 *
358 361 * input: result of first hash
359 362 * key: passwd upper 7 bytes
360 363 * output: session_key
361 364 *
362 365 * The final output should be the session key.
363 366 *
364 367 * FYI: smb_auth_DES(output, key, input)
365 368 *
366 369 * If any difficulties occur using the cryptographic framework, the
367 370 * function returns SMBAUTH_FAILURE. Otherwise SMBAUTH_SUCCESS is
368 371 * returned.
369 372 */
370 373 int
371 374 netr_gen_skey64(netr_info_t *netr_info)
372 375 {
373 376 unsigned char md4hash[32];
374 377 unsigned char buffer[8];
375 378 DWORD data[2];
376 379 DWORD *client_challenge;
377 380 DWORD *server_challenge;
378 381 int rc;
379 382 DWORD le_data[2];
380 383
381 384 client_challenge = (DWORD *)(uintptr_t)&netr_info->client_challenge;
382 385 server_challenge = (DWORD *)(uintptr_t)&netr_info->server_challenge;
383 386 bzero(md4hash, 32);
384 387
385 388 /*
386 389 * We should check (netr_info->flags & NETR_FLG_INIT) and use
387 390 * the appropriate password but it isn't working yet. So we
388 391 * always use the default one for now.
389 392 */
390 393 bzero(netr_info->password, sizeof (netr_info->password));
391 394 rc = smb_config_getstr(SMB_CI_MACHINE_PASSWD,
392 395 (char *)netr_info->password, sizeof (netr_info->password));
393 396
394 397 if ((rc != SMBD_SMF_OK) || *netr_info->password == '\0') {
395 398 return (SMBAUTH_FAILURE);
396 399 }
397 400
398 401 rc = smb_auth_ntlm_hash((char *)netr_info->password, md4hash);
399 402
400 403 if (rc != SMBAUTH_SUCCESS)
401 404 return (SMBAUTH_FAILURE);
402 405
403 406 data[0] = LE_IN32(&client_challenge[0]) + LE_IN32(&server_challenge[0]);
404 407 data[1] = LE_IN32(&client_challenge[1]) + LE_IN32(&server_challenge[1]);
405 408 LE_OUT32(&le_data[0], data[0]);
406 409 LE_OUT32(&le_data[1], data[1]);
407 410 rc = smb_auth_DES(buffer, 8, md4hash, NETR_DESKEY_LEN,
408 411 (unsigned char *)le_data, 8);
409 412
410 413 if (rc != SMBAUTH_SUCCESS)
411 414 return (rc);
412 415
413 416 netr_info->session_key.len = NETR_SESSKEY64_SZ;
414 417 rc = smb_auth_DES(netr_info->session_key.key,
415 418 netr_info->session_key.len, &md4hash[9], NETR_DESKEY_LEN, buffer,
416 419 8);
417 420
418 421 return (rc);
419 422 }
420 423
421 424 /*
422 425 * netr_gen_credentials
423 426 *
424 427 * Generate a set of credentials from a challenge and a session key.
425 428 * The algorithm is a two stage hash. For the first hash, the
426 429 * timestamp is added to the challenge and the result is stored in a
427 430 * temporary buffer:
428 431 *
429 432 * input: challenge (including timestamp)
430 433 * key: session_key
431 434 * output: intermediate result
432 435 *
433 436 * For the second hash, the input is the result of the first hash and
434 437 * a strange partial key is used:
435 438 *
436 439 * input: result of first hash
437 440 * key: funny partial key
438 441 * output: credentiails
439 442 *
440 443 * The final output should be an encrypted set of credentials.
441 444 *
442 445 * FYI: smb_auth_DES(output, key, input)
443 446 *
444 447 * If any difficulties occur using the cryptographic framework, the
445 448 * function returns SMBAUTH_FAILURE. Otherwise SMBAUTH_SUCCESS is
446 449 * returned.
447 450 */
448 451 int
449 452 netr_gen_credentials(BYTE *session_key, netr_cred_t *challenge,
450 453 DWORD timestamp, netr_cred_t *out_cred)
451 454 {
452 455 unsigned char buffer[8];
453 456 DWORD data[2];
454 457 DWORD le_data[2];
455 458 DWORD *p;
456 459 int rc;
457 460
458 461 p = (DWORD *)(uintptr_t)challenge;
459 462 data[0] = LE_IN32(&p[0]) + timestamp;
460 463 data[1] = LE_IN32(&p[1]);
461 464
462 465 LE_OUT32(&le_data[0], data[0]);
463 466 LE_OUT32(&le_data[1], data[1]);
464 467
465 468 if (smb_auth_DES(buffer, 8, session_key, NETR_DESKEY_LEN,
466 469 (unsigned char *)le_data, 8) != SMBAUTH_SUCCESS)
467 470 return (SMBAUTH_FAILURE);
468 471
469 472 rc = smb_auth_DES(out_cred->data, 8, &session_key[NETR_DESKEY_LEN],
470 473 NETR_DESKEY_LEN, buffer, 8);
471 474
472 475 return (rc);
473 476 }
474 477
475 478 /*
476 479 * netr_server_password_set
477 480 *
478 481 * Attempt to change the trust account password for this system.
479 482 *
480 483 * Note that this call may legitimately fail if the registry on the
481 484 * domain controller has been setup to deny attempts to change the
482 485 * trust account password. In this case we should just continue to
483 486 * use the original password.
484 487 *
485 488 * Possible status values:
486 489 * NT_STATUS_ACCESS_DENIED
487 490 */
488 491 int
489 492 netr_server_password_set(mlsvc_handle_t *netr_handle, netr_info_t *netr_info)
490 493 {
491 494 struct netr_PasswordSet arg;
492 495 int opnum;
493 496 BYTE new_password[NETR_OWF_PASSWORD_SZ];
494 497 char account_name[NETBIOS_NAME_SZ * 2];
495 498
496 499 bzero(&arg, sizeof (struct netr_PasswordSet));
497 500 opnum = NETR_OPNUM_ServerPasswordSet;
498 501
499 502 (void) snprintf(account_name, sizeof (account_name), "%s$",
500 503 netr_info->hostname);
501 504
502 505 arg.servername = (unsigned char *)netr_info->server;
503 506 arg.account_name = (unsigned char *)account_name;
504 507 arg.sec_chan_type = NETR_WKSTA_TRUST_ACCOUNT_TYPE;
505 508 arg.hostname = (unsigned char *)netr_info->hostname;
506 509
507 510 /*
508 511 * Set up the client side authenticator.
509 512 */
510 513 if (netr_setup_authenticator(netr_info, &arg.auth, 0) !=
511 514 SMBAUTH_SUCCESS) {
512 515 return (-1);
513 516 }
514 517
515 518 /*
516 519 * Generate a new password from the old password.
517 520 */
518 521 if (netr_gen_password(netr_info->session_key.key,
519 522 netr_info->password, new_password) == SMBAUTH_FAILURE) {
520 523 return (-1);
521 524 }
522 525
523 526 (void) memcpy(&arg.owf_password, &new_password,
524 527 NETR_OWF_PASSWORD_SZ);
525 528
526 529 if (ndr_rpc_call(netr_handle, opnum, &arg) != 0)
527 530 return (-1);
528 531
529 532 if (arg.status != 0) {
530 533 ndr_rpc_status(netr_handle, opnum, arg.status);
531 534 ndr_rpc_release(netr_handle);
532 535 return (-1);
533 536 }
534 537
535 538 /*
536 539 * Check the returned credentials. The server returns the new
537 540 * client credential rather than the new server credentiali,
538 541 * as documented elsewhere.
539 542 *
540 543 * Generate the new seed for the credential chain. Increment
541 544 * the timestamp and add it to the client challenge. Then we
542 545 * need to copy the challenge to the credential field in
543 546 * preparation for the next cycle.
544 547 */
545 548 if (netr_validate_chain(netr_info, &arg.auth) == 0) {
546 549 /*
547 550 * Save the new password.
548 551 */
549 552 (void) memcpy(netr_info->password, new_password,
550 553 NETR_OWF_PASSWORD_SZ);
551 554 }
552 555
553 556 ndr_rpc_release(netr_handle);
554 557 return (0);
555 558 }
556 559
557 560 /*
558 561 * netr_gen_password
559 562 *
560 563 * Generate a new pasword from the old password and the session key.
561 564 * The algorithm is a two stage hash. The session key is used in the
562 565 * first hash but only part of the session key is used in the second
563 566 * hash.
564 567 *
565 568 * If any difficulties occur using the cryptographic framework, the
566 569 * function returns SMBAUTH_FAILURE. Otherwise SMBAUTH_SUCCESS is
567 570 * returned.
568 571 */
569 572 static int
570 573 netr_gen_password(BYTE *session_key, BYTE *old_password, BYTE *new_password)
571 574 {
572 575 int rv;
573 576
574 577 rv = smb_auth_DES(new_password, 8, session_key, NETR_DESKEY_LEN,
575 578 old_password, 8);
576 579 if (rv != SMBAUTH_SUCCESS)
577 580 return (rv);
578 581
579 582 rv = smb_auth_DES(&new_password[8], 8, &session_key[NETR_DESKEY_LEN],
580 583 NETR_DESKEY_LEN, &old_password[8], 8);
581 584 return (rv);
582 585 }
583 586
584 587 /*
585 588 * Todo: need netr_server_password_set2()
586 589 * used by "unsecure join". (NX 11960)
587 590 */
↓ open down ↓ |
355 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX