3318238fda573c819519d55be60338bd81b070ab
[bbaumbach/samba-autobuild/.git] / source4 / auth / auth_sam.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Password and authentication handling
4    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2001-2004
5    Copyright (C) Gerald Carter                             2003
6    Copyright (C) Stefan Metzmacher                         2005
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24 #include "librpc/gen_ndr/ndr_samr.h"
25 #include "system/time.h"
26 #include "auth/auth.h"
27 #include "lib/ldb/include/ldb.h"
28 #include "pstring.h"
29
30 /****************************************************************************
31  Do a specific test for an smb password being correct, given a smb_password and
32  the lanman and NT responses.
33 ****************************************************************************/
34 static NTSTATUS authsam_password_ok(const struct auth_context *auth_context,
35                                     TALLOC_CTX *mem_ctx,
36                                     uint16_t acct_flags,
37                                     const struct samr_Password *lm_pwd, 
38                                     const struct samr_Password *nt_pwd,
39                                     const struct auth_usersupplied_info *user_info, 
40                                     DATA_BLOB *user_sess_key, 
41                                     DATA_BLOB *lm_sess_key)
42 {
43         NTSTATUS status;
44
45         if (acct_flags & ACB_PWNOTREQ) {
46                 if (lp_null_passwords()) {
47                         DEBUG(3,("Account for user '%s' has no password and null passwords are allowed.\n", 
48                                  user_info->account_name));
49                         return NT_STATUS_OK;
50                 } else {
51                         DEBUG(3,("Account for user '%s' has no password and null passwords are NOT allowed.\n", 
52                                  user_info->account_name));
53                         return NT_STATUS_LOGON_FAILURE;
54                 }               
55         }
56
57         status = ntlm_password_check(mem_ctx, &auth_context->challenge.data, 
58                                      &user_info->lm_resp, &user_info->nt_resp, 
59                                      &user_info->lm_interactive_password, 
60                                      &user_info->nt_interactive_password,
61                                      user_info->account_name,
62                                      user_info->client.account_name, 
63                                      user_info->client.domain_name, 
64                                      lm_pwd->hash, nt_pwd->hash,
65                                      user_sess_key, lm_sess_key);
66         NT_STATUS_NOT_OK_RETURN(status);
67
68         if (user_sess_key && user_sess_key->data) {
69                 talloc_steal(auth_context, user_sess_key->data);
70         }
71         if (lm_sess_key && lm_sess_key->data) {
72                 talloc_steal(auth_context, lm_sess_key->data);
73         }
74
75         return NT_STATUS_OK;
76 }
77
78
79 /****************************************************************************
80  Do a specific test for a SAM_ACCOUNT being vaild for this connection 
81  (ie not disabled, expired and the like).
82 ****************************************************************************/
83 static NTSTATUS authsam_account_ok(TALLOC_CTX *mem_ctx,
84                                    uint16_t acct_flags,
85                                    NTTIME acct_expiry,
86                                    NTTIME must_change_time,
87                                    NTTIME last_set_time,
88                                    const char *workstation_list,
89                                    const struct auth_usersupplied_info *user_info)
90 {
91         DEBUG(4,("authsam_account_ok: Checking SMB password for user %s\n", user_info->account_name));
92
93         /* Quit if the account was disabled. */
94         if (acct_flags & ACB_DISABLED) {
95                 DEBUG(1,("authsam_account_ok: Account for user '%s' was disabled.\n", user_info->account_name));
96                 return NT_STATUS_ACCOUNT_DISABLED;
97         }
98
99         /* Quit if the account was locked out. */
100         if (acct_flags & ACB_AUTOLOCK) {
101                 DEBUG(1,("authsam_account_ok: Account for user %s was locked out.\n", user_info->account_name));
102                 return NT_STATUS_ACCOUNT_LOCKED_OUT;
103         }
104
105         /* Test account expire time */
106         if ((acct_expiry) != -1 && time(NULL) > nt_time_to_unix(acct_expiry)) {
107                 DEBUG(1,("authsam_account_ok: Account for user '%s' has expired.\n", user_info->account_name));
108                 DEBUG(3,("authsam_account_ok: Account expired at '%s'.\n", 
109                          nt_time_string(mem_ctx, acct_expiry)));
110                 return NT_STATUS_ACCOUNT_EXPIRED;
111         }
112
113         if (!(acct_flags & ACB_PWNOEXP)) {
114                 /* check for immediate expiry "must change at next logon" */
115                 if (must_change_time == 0 && last_set_time != 0) {
116                         DEBUG(1,("sam_account_ok: Account for user '%s' password must change!.\n", 
117                                  user_info->account_name));
118                         return NT_STATUS_PASSWORD_MUST_CHANGE;
119                 }
120
121                 /* check for expired password */
122                 if ((must_change_time) != 0 && nt_time_to_unix(must_change_time) < time(NULL)) {
123                         DEBUG(1,("sam_account_ok: Account for user '%s' password expired!.\n", 
124                                  user_info->account_name));
125                         DEBUG(1,("sam_account_ok: Password expired at '%s' unix time.\n", 
126                                  nt_time_string(mem_ctx, must_change_time)));
127                         return NT_STATUS_PASSWORD_EXPIRED;
128                 }
129         }
130
131         /* Test workstation. Workstation list is comma separated. */
132         if (workstation_list && *workstation_list) {
133                 BOOL invalid_ws = True;
134                 const char *s = workstation_list;
135                         
136                 fstring tok;
137                         
138                 while (next_token(&s, tok, ",", sizeof(tok))) {
139                         DEBUG(10,("sam_account_ok: checking for workstation match '%s' and '%s'\n",
140                                   tok, user_info->workstation_name));
141
142                         if (strequal(tok, user_info->workstation_name)) {
143                                 invalid_ws = False;
144
145                                 break;
146                         }
147                 }
148
149                 if (invalid_ws) {
150                         return NT_STATUS_INVALID_WORKSTATION;
151                 }
152         }
153
154         if (acct_flags & ACB_DOMTRUST) {
155                 DEBUG(2,("sam_account_ok: Domain trust account %s denied by server\n", user_info->account_name));
156                 return NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT;
157         }
158
159         if (acct_flags & ACB_SVRTRUST) {
160                 DEBUG(2,("sam_account_ok: Server trust account %s denied by server\n", user_info->account_name));
161                 return NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT;
162         }
163
164         if (acct_flags & ACB_WSTRUST) {
165                 DEBUG(4,("sam_account_ok: Wksta trust account %s denied by server\n", user_info->account_name));
166                 return NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT;
167         }
168
169         return NT_STATUS_OK;
170 }
171
172 /****************************************************************************
173  Look for the specified user in the sam, return ldb result structures
174 ****************************************************************************/
175
176 static NTSTATUS authsam_search_account(TALLOC_CTX *mem_ctx, struct ldb_context *sam_ctx,
177                                        const char *account_name,
178                                        const char *domain_name,
179                                        struct ldb_message ***ret_msgs,
180                                        struct ldb_message ***ret_msgs_domain)
181 {
182         struct ldb_message **msgs_tmp;
183         struct ldb_message **msgs;
184         struct ldb_message **msgs_domain;
185
186         int ret;
187         int ret_domain;
188
189         const char *domain_dn = NULL;
190
191         const char *attrs[] = {"unicodePwd", "lmPwdHash", "ntPwdHash",
192                                "userAccountControl",
193                                "pwdLastSet",
194                                "accountExpires",
195                                "objectSid",
196                                "userWorkstations",
197                                
198                                /* required for server_info, not access control: */
199                                "sAMAccountName",
200                                "displayName",
201                                "scriptPath",
202                                "profilePath",
203                                "homeDirectory",
204                                "homeDrive",
205                                "lastLogon",
206                                "lastLogoff",
207                                "accountExpires",
208                                "badPwdCount",
209                                "logonCount",
210                                "primaryGroupID",
211                                NULL,
212         };
213
214         const char *domain_attrs[] =  {"nETBIOSName", "nCName"};
215
216         if (domain_name) {
217                 /* find the domain's DN */
218                 ret_domain = gendb_search(sam_ctx, mem_ctx, NULL, &msgs_domain, domain_attrs,
219                                           "(&(&(|(&(dnsRoot=%s)(nETBIOSName=*))(nETBIOSName=%s))(objectclass=crossRef))(ncName=*))", 
220                                           domain_name, domain_name);
221                 if (ret_domain == -1) {
222                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
223                 }
224
225                 if (ret_domain == 0) {
226                         DEBUG(3,("sam_search_user: Couldn't find domain [%s] in samdb.\n", 
227                                  domain_name));
228                         return NT_STATUS_NO_SUCH_USER;
229                 }
230
231                 if (ret_domain > 1) {
232                         DEBUG(0,("Found %d records matching domain [%s]\n", 
233                                  ret_domain, domain_name));
234                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
235                 }
236
237                 domain_dn = samdb_result_string(msgs_domain[0], "nCName", NULL);
238         }
239
240         /* pull the user attributes */
241         ret = gendb_search(sam_ctx, mem_ctx, domain_dn, &msgs, attrs,
242                            "(&(sAMAccountName=%s)(objectclass=user))", 
243                            account_name);
244         if (ret == -1) {
245                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
246         }
247
248         if (ret == 0) {
249                 DEBUG(3,("sam_search_user: Couldn't find user [%s] in samdb.\n", 
250                          account_name));
251                 return NT_STATUS_NO_SUCH_USER;
252         }
253
254         if (ret > 1) {
255                 DEBUG(0,("Found %d records matching user [%s]\n", ret, account_name));
256                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
257         }
258
259         if (!domain_name) {
260                 struct dom_sid *domain_sid;
261
262                 domain_sid = samdb_result_sid_prefix(mem_ctx, msgs[0], "objectSid");
263                 if (!domain_sid) {
264                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
265                 }
266
267                 /* find the domain's DN */
268                 ret = gendb_search(sam_ctx, mem_ctx, NULL, &msgs_tmp, NULL,
269                                    "(&(objectSid=%s)(objectclass=domain))", 
270                                    ldap_encode_ndr_dom_sid(mem_ctx, domain_sid));
271                 if (ret == -1) {
272                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
273                 }
274                 
275                 if (ret == 0) {
276                         DEBUG(3,("check_sam_security: Couldn't find domain_sid [%s] in passdb file.\n",
277                                  dom_sid_string(mem_ctx, domain_sid)));
278                         return NT_STATUS_NO_SUCH_USER;
279                 }
280                 
281                 if (ret > 1) {
282                         DEBUG(0,("Found %d records matching domain_sid [%s]\n", 
283                                  ret, dom_sid_string(mem_ctx, domain_sid)));
284                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
285                 }
286
287                 ret_domain = gendb_search(sam_ctx, mem_ctx, NULL, &msgs_domain, domain_attrs,
288                                           "(nCName=%s)", msgs_tmp[0]->dn);
289
290                 if (ret_domain == -1) {
291                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
292                 }
293                 
294                 if (ret_domain == 0) {
295                         DEBUG(3,("check_sam_security: Couldn't find domain [%s] in passdb file.\n",
296                                  msgs_tmp[0]->dn));
297                         return NT_STATUS_NO_SUCH_USER;
298                 }
299                 
300                 if (ret_domain > 1) {
301                         DEBUG(0,("Found %d records matching domain [%s]\n", 
302                                  ret_domain, msgs_tmp[0]->dn));
303                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
304                 }
305
306         }
307
308         *ret_msgs = msgs;
309         *ret_msgs_domain = msgs_domain;
310         
311         return NT_STATUS_OK;
312 }
313
314 static NTSTATUS authsam_authenticate(const struct auth_context *auth_context, 
315                                      TALLOC_CTX *mem_ctx, struct ldb_context *sam_ctx, 
316                                      struct ldb_message **msgs,
317                                      struct ldb_message **msgs_domain,
318                                      const struct auth_usersupplied_info *user_info, 
319                                      DATA_BLOB *user_sess_key, DATA_BLOB *lm_sess_key) 
320 {
321         uint16_t acct_flags;
322         const char *workstation_list;
323         NTTIME acct_expiry;
324         NTTIME must_change_time;
325         NTTIME last_set_time;
326         struct samr_Password *lm_pwd, *nt_pwd;
327         NTSTATUS nt_status;
328         const char *domain_dn = samdb_result_string(msgs_domain[0], "nCName", "");
329
330         acct_flags = samdb_result_acct_flags(msgs[0], "sAMAcctFlags");
331         
332         /* Quit if the account was locked out. */
333         if (acct_flags & ACB_AUTOLOCK) {
334                 DEBUG(3,("check_sam_security: Account for user %s was locked out.\n", 
335                          user_info->account_name));
336                 return NT_STATUS_ACCOUNT_LOCKED_OUT;
337         }
338
339         nt_status = samdb_result_passwords(mem_ctx, msgs[0], &lm_pwd, &nt_pwd);
340         NT_STATUS_NOT_OK_RETURN(nt_status);
341
342         nt_status = authsam_password_ok(auth_context, mem_ctx, 
343                                         acct_flags, lm_pwd, nt_pwd,
344                                         user_info, user_sess_key, lm_sess_key);
345         NT_STATUS_NOT_OK_RETURN(nt_status);
346
347         acct_expiry = samdb_result_nttime(msgs[0], "accountExpires", 0);
348         must_change_time = samdb_result_force_password_change(sam_ctx, mem_ctx, 
349                                                               domain_dn, msgs[0], 
350                                                               "pwdLastSet");
351         last_set_time = samdb_result_nttime(msgs[0], "pwdLastSet", 0);
352
353         workstation_list = samdb_result_string(msgs[0], "userWorkstations", NULL);
354
355         nt_status = authsam_account_ok(mem_ctx, acct_flags, 
356                                        acct_expiry, 
357                                        must_change_time, 
358                                        last_set_time, 
359                                        workstation_list,
360                                        user_info);
361
362         return nt_status;
363 }
364
365 static NTSTATUS authsam_make_server_info(TALLOC_CTX *mem_ctx, struct ldb_context *sam_ctx,
366                                          struct ldb_message **msgs,
367                                          struct ldb_message **msgs_domain,
368                                          DATA_BLOB user_sess_key, DATA_BLOB lm_sess_key,
369                                          struct auth_serversupplied_info **_server_info)
370 {
371         struct auth_serversupplied_info *server_info;
372         struct ldb_message **group_msgs;
373         int group_ret;
374         const char *group_attrs[3] = { "sAMAccountType", "objectSid", NULL }; 
375         /* find list of sids */
376         struct dom_sid **groupSIDs = NULL;
377         struct dom_sid *account_sid;
378         struct dom_sid *primary_group_sid;
379         const char *str, *ncname;
380         int i;
381         uint_t rid;
382         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
383
384         group_ret = gendb_search(sam_ctx,
385                                  tmp_ctx, NULL, &group_msgs, group_attrs,
386                                  "(&(member=%s)(sAMAccountType=*))", 
387                                  msgs[0]->dn);
388         if (group_ret == -1) {
389                 talloc_free(tmp_ctx);
390                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
391         }
392
393         server_info = talloc(mem_ctx, struct auth_serversupplied_info);
394         NT_STATUS_HAVE_NO_MEMORY(server_info);
395         
396         if (group_ret > 0) {
397                 groupSIDs = talloc_array(server_info, struct dom_sid *, group_ret);
398                 NT_STATUS_HAVE_NO_MEMORY(groupSIDs);
399         }
400
401         /* Need to unroll some nested groups, but not aliases */
402         for (i = 0; i < group_ret; i++) {
403                 groupSIDs[i] = samdb_result_dom_sid(groupSIDs, 
404                                                     group_msgs[i], "objectSid");
405                 NT_STATUS_HAVE_NO_MEMORY(groupSIDs[i]);
406         }
407
408         talloc_free(tmp_ctx);
409
410         account_sid = samdb_result_dom_sid(server_info, msgs[0], "objectSid");
411         NT_STATUS_HAVE_NO_MEMORY(account_sid);
412
413         primary_group_sid = dom_sid_dup(server_info, account_sid);
414         NT_STATUS_HAVE_NO_MEMORY(primary_group_sid);
415
416         rid = samdb_result_uint(msgs[0], "primaryGroupID", ~0);
417         if (rid == ~0) {
418                 if (group_ret > 0) {
419                         primary_group_sid = groupSIDs[0];
420                 } else {
421                         primary_group_sid = NULL;
422                 }
423         } else {
424                 primary_group_sid->sub_auths[primary_group_sid->num_auths-1] = rid;
425         }
426
427         server_info->account_sid = account_sid;
428         server_info->primary_group_sid = primary_group_sid;
429         
430         server_info->n_domain_groups = group_ret;
431         server_info->domain_groups = groupSIDs;
432
433         server_info->account_name = talloc_steal(server_info, samdb_result_string(msgs[0], "sAMAccountName", NULL));
434
435         server_info->domain_name = talloc_steal(server_info, samdb_result_string(msgs_domain[0], "nETBIOSName", NULL));
436
437         str = samdb_result_string(msgs[0], "displayName", "");
438         server_info->full_name = talloc_strdup(server_info, str);
439         NT_STATUS_HAVE_NO_MEMORY(server_info->full_name);
440
441         str = samdb_result_string(msgs[0], "scriptPath", "");
442         server_info->logon_script = talloc_strdup(server_info, str);
443         NT_STATUS_HAVE_NO_MEMORY(server_info->logon_script);
444
445         str = samdb_result_string(msgs[0], "profilePath", "");
446         server_info->profile_path = talloc_strdup(server_info, str);
447         NT_STATUS_HAVE_NO_MEMORY(server_info->profile_path);
448
449         str = samdb_result_string(msgs[0], "homeDirectory", "");
450         server_info->home_directory = talloc_strdup(server_info, str);
451         NT_STATUS_HAVE_NO_MEMORY(server_info->home_directory);
452
453         str = samdb_result_string(msgs[0], "homeDrive", "");
454         server_info->home_drive = talloc_strdup(server_info, str);
455         NT_STATUS_HAVE_NO_MEMORY(server_info->home_drive);
456
457         server_info->last_logon = samdb_result_nttime(msgs[0], "lastLogon", 0);
458         server_info->last_logoff = samdb_result_nttime(msgs[0], "lastLogoff", 0);
459         server_info->acct_expiry = samdb_result_nttime(msgs[0], "accountExpires", 0);
460         server_info->last_password_change = samdb_result_nttime(msgs[0], "pwdLastSet", 0);
461
462         ncname = samdb_result_string(msgs_domain[0], "nCName", "");
463
464         server_info->allow_password_change = samdb_result_allow_password_change(sam_ctx, mem_ctx, 
465                                                         ncname, msgs[0], "pwdLastSet");
466         server_info->force_password_change = samdb_result_force_password_change(sam_ctx, mem_ctx, 
467                                                         ncname, msgs[0], "pwdLastSet");
468
469         server_info->logon_count = samdb_result_uint(msgs[0], "logonCount", 0);
470         server_info->bad_password_count = samdb_result_uint(msgs[0], "badPwdCount", 0);
471
472         server_info->acct_flags = samdb_result_acct_flags(msgs[0], "userAccountControl");
473
474         server_info->user_session_key = user_sess_key;
475         server_info->lm_session_key = lm_sess_key;
476
477         server_info->authenticated = True;
478
479         *_server_info = server_info;
480
481         return NT_STATUS_OK;
482 }
483
484 NTSTATUS sam_get_server_info(TALLOC_CTX *mem_ctx, const char *account_name, const char *domain_name,
485                              DATA_BLOB user_sess_key, DATA_BLOB lm_sess_key,
486                              struct auth_serversupplied_info **server_info)
487 {
488         NTSTATUS nt_status;
489
490         struct ldb_message **msgs;
491         struct ldb_message **domain_msgs;
492         void *sam_ctx;
493
494         sam_ctx = samdb_connect(mem_ctx);
495         if (sam_ctx == NULL) {
496                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
497         }
498
499         nt_status = authsam_search_account(mem_ctx, sam_ctx, account_name, domain_name, &msgs, &domain_msgs);
500         NT_STATUS_NOT_OK_RETURN(nt_status);
501
502         nt_status = authsam_make_server_info(mem_ctx, sam_ctx, msgs, domain_msgs,
503                                              user_sess_key, lm_sess_key,
504                                              server_info);
505         NT_STATUS_NOT_OK_RETURN(nt_status);
506
507         talloc_free(msgs);
508         talloc_free(domain_msgs);
509
510         return NT_STATUS_OK;
511 }
512
513 static NTSTATUS authsam_check_password_internals(struct auth_method_context *ctx,
514                                                  TALLOC_CTX *mem_ctx,
515                                                  const char *domain,
516                                                  const struct auth_usersupplied_info *user_info, 
517                                                  struct auth_serversupplied_info **server_info)
518 {
519         NTSTATUS nt_status;
520         const char *account_name = user_info->account_name;
521         struct ldb_message **msgs;
522         struct ldb_message **domain_msgs;
523         struct ldb_context *sam_ctx;
524         DATA_BLOB user_sess_key, lm_sess_key;
525
526         if (!account_name || !*account_name) {
527                 /* 'not for me' */
528                 return NT_STATUS_NOT_IMPLEMENTED;
529         }
530
531         sam_ctx = samdb_connect(mem_ctx);
532         if (sam_ctx == NULL) {
533                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
534         }
535
536         nt_status = authsam_search_account(mem_ctx, sam_ctx, account_name, domain, &msgs, &domain_msgs);
537         NT_STATUS_NOT_OK_RETURN(nt_status);
538
539         nt_status = authsam_authenticate(ctx->auth_ctx, mem_ctx, sam_ctx, msgs, domain_msgs, user_info,
540                                          &user_sess_key, &lm_sess_key);
541         NT_STATUS_NOT_OK_RETURN(nt_status);
542
543         nt_status = authsam_make_server_info(mem_ctx, sam_ctx, msgs, domain_msgs,
544                                              user_sess_key, lm_sess_key,
545                                              server_info);
546         NT_STATUS_NOT_OK_RETURN(nt_status);
547
548         talloc_free(msgs);
549         talloc_free(domain_msgs);
550
551         return NT_STATUS_OK;
552 }
553
554 static NTSTATUS authsam_ignoredomain_check_password(struct auth_method_context *ctx,
555                                                     TALLOC_CTX *mem_ctx,
556                                                     const struct auth_usersupplied_info *user_info, 
557                                                     struct auth_serversupplied_info **server_info)
558 {
559         return authsam_check_password_internals(ctx, mem_ctx, NULL, user_info, server_info);
560 }
561
562 /****************************************************************************
563 Check SAM security (above) but with a few extra checks.
564 ****************************************************************************/
565 static NTSTATUS authsam_check_password(struct auth_method_context *ctx,
566                                        TALLOC_CTX *mem_ctx,
567                                        const struct auth_usersupplied_info *user_info, 
568                                        struct auth_serversupplied_info **server_info)
569 {
570         const char *domain;
571         BOOL is_local_name, is_my_domain;
572
573         is_local_name = is_myname(user_info->domain_name);
574         is_my_domain  = strequal(user_info->domain_name, lp_workgroup());
575
576         /* check whether or not we service this domain/workgroup name */
577         switch (lp_server_role()) {
578                 case ROLE_STANDALONE:
579                         domain = lp_netbios_name();
580                         break;
581                 case ROLE_DOMAIN_MEMBER:
582                         if (!is_local_name) {
583                                 DEBUG(6,("authsam_check_password: %s is not one of my local names (%s)\n",
584                                         user_info->domain_name, (lp_server_role() == ROLE_DOMAIN_MEMBER 
585                                         ? "ROLE_DOMAIN_MEMBER" : "ROLE_STANDALONE") ));
586                                 return NT_STATUS_NOT_IMPLEMENTED;
587                         }
588                         domain = lp_netbios_name();
589                         break;
590                 case ROLE_DOMAIN_PDC:
591                 case ROLE_DOMAIN_BDC:
592                         if (!is_local_name && !is_my_domain) {
593                                 DEBUG(6,("authsam_check_password: %s is not one of my local names or domain name (DC)\n",
594                                         user_info->domain_name));
595                                 return NT_STATUS_NOT_IMPLEMENTED;
596                         }
597                         domain = lp_workgroup();
598                         break;
599                 default:
600                         DEBUG(6,("authsam_check_password: lp_server_role() has an undefined value\n"));
601                         return NT_STATUS_NOT_IMPLEMENTED;
602         }
603
604         return authsam_check_password_internals(ctx, mem_ctx, domain, user_info, server_info);
605 }
606
607 static const struct auth_operations sam_ignoredomain_ops = {
608         .name           = "sam_ignoredomain",
609         .get_challenge  = auth_get_challenge_not_implemented,
610         .check_password = authsam_ignoredomain_check_password
611 };
612
613 static const struct auth_operations sam_ops = {
614         .name           = "sam",
615         .get_challenge  = auth_get_challenge_not_implemented,
616         .check_password = authsam_check_password
617 };
618
619 NTSTATUS auth_sam_init(void)
620 {
621         NTSTATUS ret;
622
623         ret = auth_register(&sam_ops);
624         if (!NT_STATUS_IS_OK(ret)) {
625                 DEBUG(0,("Failed to register 'sam' auth backend!\n"));
626                 return ret;
627         }
628
629         ret = auth_register(&sam_ignoredomain_ops);
630         if (!NT_STATUS_IS_OK(ret)) {
631                 DEBUG(0,("Failed to register 'sam_ignoredomain' auth backend!\n"));
632                 return ret;
633         }
634
635         return ret;
636 }