Ignore:
Timestamp:
Nov 27, 2012, 4:43:17 PM (13 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: updated trunk to 3.6.0

Location:
trunk/server
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/server

  • trunk/server/source3/winbindd/winbindd_pam.c

    r599 r745  
    2626#include "winbindd.h"
    2727#include "../libcli/auth/libcli_auth.h"
    28 #include "../librpc/gen_ndr/cli_samr.h"
     28#include "../librpc/gen_ndr/ndr_samr_c.h"
     29#include "rpc_client/cli_pipe.h"
     30#include "rpc_client/cli_samr.h"
     31#include "../librpc/gen_ndr/ndr_netlogon.h"
     32#include "rpc_client/cli_netlogon.h"
    2933#include "smb_krb5.h"
     34#include "../lib/crypto/arcfour.h"
     35#include "../libcli/security/security.h"
     36#include "ads.h"
     37#include "../librpc/gen_ndr/krb5pac.h"
     38#include "passdb/machine_sid.h"
     39#include "auth.h"
    3040
    3141#undef DBGC_CLASS
     
    3545
    3646static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx,
    37                                     struct winbindd_cli_state *state,
     47                                    struct winbindd_response *resp,
    3848                                    struct netr_SamInfo3 *info3)
    3949{
     
    4151        uint32_t i;
    4252
    43         state->response->data.auth.info3.logon_time =
     53        resp->data.auth.info3.logon_time =
    4454                nt_time_to_unix(info3->base.last_logon);
    45         state->response->data.auth.info3.logoff_time =
     55        resp->data.auth.info3.logoff_time =
    4656                nt_time_to_unix(info3->base.last_logoff);
    47         state->response->data.auth.info3.kickoff_time =
     57        resp->data.auth.info3.kickoff_time =
    4858                nt_time_to_unix(info3->base.acct_expiry);
    49         state->response->data.auth.info3.pass_last_set_time =
     59        resp->data.auth.info3.pass_last_set_time =
    5060                nt_time_to_unix(info3->base.last_password_change);
    51         state->response->data.auth.info3.pass_can_change_time =
     61        resp->data.auth.info3.pass_can_change_time =
    5262                nt_time_to_unix(info3->base.allow_password_change);
    53         state->response->data.auth.info3.pass_must_change_time =
     63        resp->data.auth.info3.pass_must_change_time =
    5464                nt_time_to_unix(info3->base.force_password_change);
    5565
    56         state->response->data.auth.info3.logon_count = info3->base.logon_count;
    57         state->response->data.auth.info3.bad_pw_count = info3->base.bad_password_count;
    58 
    59         state->response->data.auth.info3.user_rid = info3->base.rid;
    60         state->response->data.auth.info3.group_rid = info3->base.primary_gid;
    61         sid_to_fstring(state->response->data.auth.info3.dom_sid, info3->base.domain_sid);
    62 
    63         state->response->data.auth.info3.num_groups = info3->base.groups.count;
    64         state->response->data.auth.info3.user_flgs = info3->base.user_flags;
    65 
    66         state->response->data.auth.info3.acct_flags = info3->base.acct_flags;
    67         state->response->data.auth.info3.num_other_sids = info3->sidcount;
    68 
    69         fstrcpy(state->response->data.auth.info3.user_name,
     66        resp->data.auth.info3.logon_count = info3->base.logon_count;
     67        resp->data.auth.info3.bad_pw_count = info3->base.bad_password_count;
     68
     69        resp->data.auth.info3.user_rid = info3->base.rid;
     70        resp->data.auth.info3.group_rid = info3->base.primary_gid;
     71        sid_to_fstring(resp->data.auth.info3.dom_sid, info3->base.domain_sid);
     72
     73        resp->data.auth.info3.num_groups = info3->base.groups.count;
     74        resp->data.auth.info3.user_flgs = info3->base.user_flags;
     75
     76        resp->data.auth.info3.acct_flags = info3->base.acct_flags;
     77        resp->data.auth.info3.num_other_sids = info3->sidcount;
     78
     79        fstrcpy(resp->data.auth.info3.user_name,
    7080                info3->base.account_name.string);
    71         fstrcpy(state->response->data.auth.info3.full_name,
     81        fstrcpy(resp->data.auth.info3.full_name,
    7282                info3->base.full_name.string);
    73         fstrcpy(state->response->data.auth.info3.logon_script,
     83        fstrcpy(resp->data.auth.info3.logon_script,
    7484                info3->base.logon_script.string);
    75         fstrcpy(state->response->data.auth.info3.profile_path,
     85        fstrcpy(resp->data.auth.info3.profile_path,
    7686                info3->base.profile_path.string);
    77         fstrcpy(state->response->data.auth.info3.home_dir,
     87        fstrcpy(resp->data.auth.info3.home_dir,
    7888                info3->base.home_directory.string);
    79         fstrcpy(state->response->data.auth.info3.dir_drive,
     89        fstrcpy(resp->data.auth.info3.dir_drive,
    8090                info3->base.home_drive.string);
    8191
    82         fstrcpy(state->response->data.auth.info3.logon_srv,
     92        fstrcpy(resp->data.auth.info3.logon_srv,
    8393                info3->base.logon_server.string);
    84         fstrcpy(state->response->data.auth.info3.logon_dom,
     94        fstrcpy(resp->data.auth.info3.logon_dom,
    8595                info3->base.domain.string);
    8696
    87         ex = talloc_strdup(state->mem_ctx, "");
     97        ex = talloc_strdup(mem_ctx, "");
    8898        NT_STATUS_HAVE_NO_MEMORY(ex);
    8999
     
    109119        }
    110120
    111         state->response->extra_data.data = ex;
    112         state->response->length += talloc_get_size(ex);
     121        resp->extra_data.data = ex;
     122        resp->length += talloc_get_size(ex);
    113123
    114124        return NT_STATUS_OK;
     
    116126
    117127static NTSTATUS append_info3_as_ndr(TALLOC_CTX *mem_ctx,
    118                                     struct winbindd_cli_state *state,
     128                                    struct winbindd_response *resp,
    119129                                    struct netr_SamInfo3 *info3)
    120130{
     
    122132        enum ndr_err_code ndr_err;
    123133
    124         ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, info3,
     134        ndr_err = ndr_push_struct_blob(&blob, mem_ctx, info3,
    125135                                       (ndr_push_flags_fn_t)ndr_push_netr_SamInfo3);
    126136        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     
    129139        }
    130140
    131         state->response->extra_data.data = blob.data;
    132         state->response->length += blob.length;
     141        resp->extra_data.data = blob.data;
     142        resp->length += blob.length;
    133143
    134144        return NT_STATUS_OK;
     
    136146
    137147static NTSTATUS append_unix_username(TALLOC_CTX *mem_ctx,
    138                                      struct winbindd_cli_state *state,
     148                                     struct winbindd_response *resp,
    139149                                     const struct netr_SamInfo3 *info3,
    140150                                     const char *name_domain,
     
    160170        }
    161171
    162         fill_domain_username(state->response->data.auth.unix_username,
     172        fill_domain_username(resp->data.auth.unix_username,
    163173                             nt_domain, nt_username, true);
    164174
    165         DEBUG(5,("Setting unix username to [%s]\n",
    166                 state->response->data.auth.unix_username));
     175        DEBUG(5, ("Setting unix username to [%s]\n",
     176                  resp->data.auth.unix_username));
    167177
    168178        return NT_STATUS_OK;
     
    170180
    171181static NTSTATUS append_afs_token(TALLOC_CTX *mem_ctx,
    172                                  struct winbindd_cli_state *state,
     182                                 struct winbindd_response *resp,
    173183                                 const struct netr_SamInfo3 *info3,
    174184                                 const char *name_domain,
     
    193203
    194204        {
    195                 DOM_SID user_sid;
     205                struct dom_sid user_sid;
    196206                fstring sidstr;
    197207
    198                 sid_copy(&user_sid, info3->base.domain_sid);
    199                 sid_append_rid(&user_sid, info3->base.rid);
     208                sid_compose(&user_sid, info3->base.domain_sid,
     209                            info3->base.rid);
    200210                sid_to_fstring(sidstr, &user_sid);
    201211                afsname = talloc_string_sub(mem_ctx, afsname,
     
    224234                return NT_STATUS_OK;
    225235        }
    226         state->response->extra_data.data = talloc_strdup(state->mem_ctx,
    227                                                          token);
    228         if (state->response->extra_data.data == NULL) {
     236        resp->extra_data.data = talloc_strdup(mem_ctx, token);
     237        if (resp->extra_data.data == NULL) {
    229238                return NT_STATUS_NO_MEMORY;
    230239        }
    231         state->response->length +=
    232                 strlen((const char *)state->response->extra_data.data)+1;
     240        resp->length += strlen((const char *)resp->extra_data.data)+1;
    233241
    234242        return NT_STATUS_OK;
    235243}
    236244
    237 NTSTATUS check_info3_in_group(struct netr_SamInfo3 *info3,
    238                               const char *group_sid)
     245static NTSTATUS check_info3_in_group(struct netr_SamInfo3 *info3,
     246                                     const char *group_sid)
    239247/**
    240248 * Check whether a user belongs to a group or list of groups.
     
    249257 */
    250258{
    251         DOM_SID *require_membership_of_sid;
    252         size_t num_require_membership_of_sid;
     259        struct dom_sid *require_membership_of_sid;
     260        uint32_t num_require_membership_of_sid;
    253261        char *req_sid;
    254262        const char *p;
    255         DOM_SID sid;
     263        struct dom_sid sid;
    256264        size_t i;
    257         struct nt_user_token *token;
     265        struct security_token *token;
    258266        TALLOC_CTX *frame = talloc_stackframe();
    259267        NTSTATUS status;
     
    266274        }
    267275
    268         token = talloc_zero(talloc_tos(), struct nt_user_token);
     276        token = talloc_zero(talloc_tos(), struct security_token);
    269277        if (token == NULL) {
    270278                DEBUG(0, ("talloc failed\n"));
     
    297305
    298306        status = sid_array_from_info3(talloc_tos(), info3,
    299                                       &token->user_sids,
     307                                      &token->sids,
    300308                                      &token->num_sids,
    301309                                      true, false);
     
    315323        }
    316324
    317         debug_nt_user_token(DBGC_CLASS, 10, token);
     325        security_token_debug(DBGC_CLASS, 10, token);
    318326
    319327        for (i=0; i<num_require_membership_of_sid; i++) {
     
    349357        }
    350358
    351         if (is_myname(domain_name)) {
    352                 DEBUG(3, ("Authentication for domain %s (local domain "
    353                           "to this server) not supported at this "
    354                           "stage\n", domain_name));
    355                 return NULL;
     359        if (strequal(domain_name, get_global_sam_name())) {
     360                return find_domain_from_name_noinit(domain_name);
    356361        }
    357362
     
    387392
    388393static NTSTATUS fillup_password_policy(struct winbindd_domain *domain,
    389                                        struct winbindd_cli_state *state)
     394                                       struct winbindd_response *response)
     395{
     396        TALLOC_CTX *frame = talloc_stackframe();
     397        struct winbindd_methods *methods;
     398        NTSTATUS status;
     399        struct samr_DomInfo1 password_policy;
     400
     401        if ( !winbindd_can_contact_domain( domain ) ) {
     402                DEBUG(5,("fillup_password_policy: No inbound trust to "
     403                         "contact domain %s\n", domain->name));
     404                status = NT_STATUS_NOT_SUPPORTED;
     405                goto done;
     406        }
     407
     408        methods = domain->methods;
     409
     410        status = methods->password_policy(domain, talloc_tos(), &password_policy);
     411        if (NT_STATUS_IS_ERR(status)) {
     412                goto done;
     413        }
     414
     415        fill_in_password_policy(response, &password_policy);
     416
     417done:
     418        TALLOC_FREE(frame);
     419        return NT_STATUS_OK;
     420}
     421
     422static NTSTATUS get_max_bad_attempts_from_lockout_policy(struct winbindd_domain *domain,
     423                                                         TALLOC_CTX *mem_ctx,
     424                                                         uint16 *lockout_threshold)
     425{
     426        struct winbindd_methods *methods;
     427        NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
     428        struct samr_DomInfo12 lockout_policy;
     429
     430        *lockout_threshold = 0;
     431
     432        methods = domain->methods;
     433
     434        status = methods->lockout_policy(domain, mem_ctx, &lockout_policy);
     435        if (NT_STATUS_IS_ERR(status)) {
     436                return status;
     437        }
     438
     439        *lockout_threshold = lockout_policy.lockout_threshold;
     440
     441        return NT_STATUS_OK;
     442}
     443
     444static NTSTATUS get_pwd_properties(struct winbindd_domain *domain,
     445                                   TALLOC_CTX *mem_ctx,
     446                                   uint32 *password_properties)
    390447{
    391448        struct winbindd_methods *methods;
     
    393450        struct samr_DomInfo1 password_policy;
    394451
    395         if ( !winbindd_can_contact_domain( domain ) ) {
    396                 DEBUG(5,("fillup_password_policy: No inbound trust to "
    397                          "contact domain %s\n", domain->name));
    398                 return NT_STATUS_NOT_SUPPORTED;
    399         }
    400 
    401         methods = domain->methods;
    402 
    403         status = methods->password_policy(domain, state->mem_ctx, &password_policy);
    404         if (NT_STATUS_IS_ERR(status)) {
    405                 return status;
    406         }
    407 
    408         fill_in_password_policy(state->response, &password_policy);
    409 
    410         return NT_STATUS_OK;
    411 }
    412 
    413 static NTSTATUS get_max_bad_attempts_from_lockout_policy(struct winbindd_domain *domain,
    414                                                          TALLOC_CTX *mem_ctx,
    415                                                          uint16 *lockout_threshold)
    416 {
    417         struct winbindd_methods *methods;
    418         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
    419         struct samr_DomInfo12 lockout_policy;
    420 
    421         *lockout_threshold = 0;
    422 
    423         methods = domain->methods;
    424 
    425         status = methods->lockout_policy(domain, mem_ctx, &lockout_policy);
    426         if (NT_STATUS_IS_ERR(status)) {
    427                 return status;
    428         }
    429 
    430         *lockout_threshold = lockout_policy.lockout_threshold;
    431 
    432         return NT_STATUS_OK;
    433 }
    434 
    435 static NTSTATUS get_pwd_properties(struct winbindd_domain *domain,
    436                                    TALLOC_CTX *mem_ctx,
    437                                    uint32 *password_properties)
    438 {
    439         struct winbindd_methods *methods;
    440         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
    441         struct samr_DomInfo1 password_policy;
    442 
    443452        *password_properties = 0;
    444453
     
    460469                                        const char *type,
    461470                                        uid_t uid,
    462                                         bool *internal_ccache)
     471                                        const char **user_ccache_file)
    463472{
    464473        /* accept FILE and WRFILE as krb5_cc_type from the client and then
     
    468477        const char *gen_cc = NULL;
    469478
    470         *internal_ccache = true;
    471 
    472         if (uid == -1) {
    473                 goto memory_ccache;
    474         }
    475 
    476         if (!type || type[0] == '\0') {
    477                 goto memory_ccache;
    478         }
    479 
    480         if (strequal(type, "FILE")) {
    481                 gen_cc = talloc_asprintf(mem_ctx, "FILE:/tmp/krb5cc_%d", uid);
    482         } else if (strequal(type, "WRFILE")) {
    483                 gen_cc = talloc_asprintf(mem_ctx, "WRFILE:/tmp/krb5cc_%d", uid);
    484         } else {
    485                 DEBUG(10,("we don't allow to set a %s type ccache\n", type));
    486                 goto memory_ccache;
    487         }
    488 
    489         *internal_ccache = false;
    490         goto done;
    491 
    492   memory_ccache:
    493         gen_cc = talloc_strdup(mem_ctx, "MEMORY:winbindd_pam_ccache");
    494 
    495   done:
     479        if (uid != -1) {
     480                if (strequal(type, "FILE")) {
     481                        gen_cc = talloc_asprintf(
     482                                mem_ctx, "FILE:/tmp/krb5cc_%d", uid);
     483                }
     484                if (strequal(type, "WRFILE")) {
     485                        gen_cc = talloc_asprintf(
     486                                mem_ctx, "WRFILE:/tmp/krb5cc_%d", uid);
     487                }
     488        }
     489
     490        *user_ccache_file = gen_cc;
     491
     492        if (gen_cc == NULL) {
     493                gen_cc = talloc_strdup(mem_ctx, "MEMORY:winbindd_pam_ccache");
     494        }
    496495        if (gen_cc == NULL) {
    497496                DEBUG(0,("out of memory\n"));
     
    499498        }
    500499
    501         DEBUG(10,("using ccache: %s %s\n", gen_cc, *internal_ccache ? "(internal)":""));
     500        DEBUG(10, ("using ccache: %s%s\n", gen_cc,
     501                   (*user_ccache_file == NULL) ? " (internal)":""));
    502502
    503503        return gen_cc;
    504504}
    505505
    506 static void setup_return_cc_name(struct winbindd_cli_state *state, const char *cc)
    507 {
    508         const char *type = state->request->data.auth.krb5_cc_type;
    509 
    510         state->response->data.auth.krb5ccname[0] = '\0';
    511 
    512         if (type[0] == '\0') {
    513                 return;
    514         }
    515 
    516         if (!strequal(type, "FILE") &&
    517             !strequal(type, "WRFILE")) {
    518                 DEBUG(10,("won't return krbccname for a %s type ccache\n",
    519                         type));
    520                 return;
    521         }
    522 
    523         fstrcpy(state->response->data.auth.krb5ccname, cc);
    524 }
    525 
    526506#endif
    527507
    528 static uid_t get_uid_from_state(struct winbindd_cli_state *state)
     508uid_t get_uid_from_request(struct winbindd_request *request)
    529509{
    530510        uid_t uid;
    531511
    532         uid = state->request->data.auth.uid;
     512        uid = request->data.auth.uid;
    533513
    534514        if (uid < 0) {
     
    544524 **********************************************************************/
    545525
    546 static NTSTATUS winbindd_raw_kerberos_login(struct winbindd_domain *domain,
    547                                             struct winbindd_cli_state *state,
    548                                             struct netr_SamInfo3 **info3)
     526static NTSTATUS winbindd_raw_kerberos_login(TALLOC_CTX *mem_ctx,
     527                                            struct winbindd_domain *domain,
     528                                            const char *user,
     529                                            const char *pass,
     530                                            const char *krb5_cc_type,
     531                                            uid_t uid,
     532                                            struct netr_SamInfo3 **info3,
     533                                            fstring krb5ccname)
    549534{
    550535#ifdef HAVE_KRB5
     
    558543        time_t ticket_lifetime = 0;
    559544        time_t renewal_until = 0;
    560         uid_t uid = -1;
    561545        ADS_STRUCT *ads;
    562546        time_t time_offset = 0;
    563         bool internal_ccache = true;
    564 
    565         ZERO_STRUCTP(info3);
     547        const char *user_ccache_file;
     548        struct PAC_LOGON_INFO *logon_info = NULL;
    566549
    567550        *info3 = NULL;
     
    570553         * prepare a krb5_cc_cache string for the user */
    571554
    572         uid = get_uid_from_state(state);
    573555        if (uid == -1) {
    574556                DEBUG(0,("no valid uid\n"));
    575557        }
    576558
    577         cc = generate_krb5_ccache(state->mem_ctx,
    578                                   state->request->data.auth.krb5_cc_type,
    579                                   state->request->data.auth.uid,
    580                                   &internal_ccache);
     559        cc = generate_krb5_ccache(mem_ctx,
     560                                  krb5_cc_type,
     561                                  uid,
     562                                  &user_ccache_file);
    581563        if (cc == NULL) {
    582564                return NT_STATUS_NO_MEMORY;
     
    596578         * do kerberos auth and setup ccache as the user */
    597579
    598         parse_domain_user(state->request->data.auth.user, name_domain, name_user);
     580        parse_domain_user(user, name_domain, name_user);
    599581
    600582        realm = domain->alt_name;
    601583        strupper_m(realm);
    602584
    603         principal_s = talloc_asprintf(state->mem_ctx, "%s@%s", name_user, realm);
     585        principal_s = talloc_asprintf(mem_ctx, "%s@%s", name_user, realm);
    604586        if (principal_s == NULL) {
    605587                return NT_STATUS_NO_MEMORY;
    606588        }
    607589
    608         service = talloc_asprintf(state->mem_ctx, "%s/%s@%s", KRB5_TGS_NAME, realm, realm);
     590        service = talloc_asprintf(mem_ctx, "%s/%s@%s", KRB5_TGS_NAME, realm, realm);
    609591        if (service == NULL) {
    610592                return NT_STATUS_NO_MEMORY;
     
    616598        /************************ ENTERING NON-ROOT **********************/
    617599
    618         if (!internal_ccache) {
     600        if (user_ccache_file != NULL) {
    619601                set_effective_uid(uid);
    620602                DEBUG(10,("winbindd_raw_kerberos_login: uid is %d\n", uid));
    621603        }
    622604
    623         result = kerberos_return_info3_from_pac(state->mem_ctx,
    624                                                 principal_s,
    625                                                 state->request->data.auth.pass,
    626                                                 time_offset,
    627                                                 &ticket_lifetime,
    628                                                 &renewal_until,
    629                                                 cc,
    630                                                 true,
    631                                                 true,
    632                                                 WINBINDD_PAM_AUTH_KRB5_RENEW_TIME,
    633                                                 NULL,
    634                                                 info3);
    635         if (!internal_ccache) {
     605        result = kerberos_return_pac(mem_ctx,
     606                                     principal_s,
     607                                     pass,
     608                                     time_offset,
     609                                     &ticket_lifetime,
     610                                     &renewal_until,
     611                                     cc,
     612                                     true,
     613                                     true,
     614                                     WINBINDD_PAM_AUTH_KRB5_RENEW_TIME,
     615                                     NULL,
     616                                     &logon_info);
     617        if (user_ccache_file != NULL) {
    636618                gain_root_privilege();
    637619        }
     
    643625        }
    644626
     627        *info3 = &logon_info->info3;
     628
    645629        DEBUG(10,("winbindd_raw_kerberos_login: winbindd validated ticket of %s\n",
    646630                principal_s));
     
    649633         * environment */
    650634
    651         if (!internal_ccache) {
    652 
    653                 setup_return_cc_name(state, cc);
     635        if (user_ccache_file != NULL) {
     636
     637                fstrcpy(krb5ccname, user_ccache_file);
    654638
    655639                result = add_ccache_to_list(principal_s,
    656640                                            cc,
    657641                                            service,
    658                                             state->request->data.auth.user,
     642                                            user,
    659643                                            realm,
    660644                                            uid,
     
    697681        }
    698682
    699         if (!NT_STATUS_IS_OK(remove_ccache(state->request->data.auth.user))) {
     683        if (!NT_STATUS_IS_OK(remove_ccache(user))) {
    700684                DEBUG(3,("winbindd_raw_kerberos_login: "
    701685                          "could not remove ccache for user %s\n",
    702                         state->request->data.auth.user));
     686                        user));
    703687        }
    704688
     
    734718****************************************************************/
    735719
    736 NTSTATUS append_auth_data(struct winbindd_cli_state *state,
    737                           struct netr_SamInfo3 *info3,
    738                           const char *name_domain,
    739                           const char *name_user)
     720static NTSTATUS append_auth_data(TALLOC_CTX *mem_ctx,
     721                                 struct winbindd_response *resp,
     722                                 uint32_t request_flags,
     723                                 struct netr_SamInfo3 *info3,
     724                                 const char *name_domain,
     725                                 const char *name_user)
    740726{
    741727        NTSTATUS result;
    742         uint32_t flags = state->request->flags;
    743 
    744         if (flags & WBFLAG_PAM_USER_SESSION_KEY) {
    745                 memcpy(state->response->data.auth.user_session_key,
     728
     729        if (request_flags & WBFLAG_PAM_USER_SESSION_KEY) {
     730                memcpy(resp->data.auth.user_session_key,
    746731                       info3->base.key.key,
    747                        sizeof(state->response->data.auth.user_session_key)
     732                       sizeof(resp->data.auth.user_session_key)
    748733                       /* 16 */);
    749734        }
    750735
    751         if (flags & WBFLAG_PAM_LMKEY) {
    752                 memcpy(state->response->data.auth.first_8_lm_hash,
     736        if (request_flags & WBFLAG_PAM_LMKEY) {
     737                memcpy(resp->data.auth.first_8_lm_hash,
    753738                       info3->base.LMSessKey.key,
    754                        sizeof(state->response->data.auth.first_8_lm_hash)
     739                       sizeof(resp->data.auth.first_8_lm_hash)
    755740                       /* 8 */);
    756741        }
    757742
    758         if (flags & WBFLAG_PAM_INFO3_TEXT) {
    759                 result = append_info3_as_txt(state->mem_ctx, state, info3);
     743        if (request_flags & WBFLAG_PAM_UNIX_NAME) {
     744                result = append_unix_username(mem_ctx, resp,
     745                                              info3, name_domain, name_user);
     746                if (!NT_STATUS_IS_OK(result)) {
     747                        DEBUG(10,("Failed to append Unix Username: %s\n",
     748                                nt_errstr(result)));
     749                        return result;
     750                }
     751        }
     752
     753        /* currently, anything from here on potentially overwrites extra_data. */
     754
     755        if (request_flags & WBFLAG_PAM_INFO3_NDR) {
     756                result = append_info3_as_ndr(mem_ctx, resp, info3);
     757                if (!NT_STATUS_IS_OK(result)) {
     758                        DEBUG(10,("Failed to append INFO3 (NDR): %s\n",
     759                                nt_errstr(result)));
     760                        return result;
     761                }
     762        }
     763
     764        if (request_flags & WBFLAG_PAM_INFO3_TEXT) {
     765                result = append_info3_as_txt(mem_ctx, resp, info3);
    760766                if (!NT_STATUS_IS_OK(result)) {
    761767                        DEBUG(10,("Failed to append INFO3 (TXT): %s\n",
     
    765771        }
    766772
    767         /* currently, anything from here on potentially overwrites extra_data. */
    768 
    769         if (flags & WBFLAG_PAM_INFO3_NDR) {
    770                 result = append_info3_as_ndr(state->mem_ctx, state, info3);
    771                 if (!NT_STATUS_IS_OK(result)) {
    772                         DEBUG(10,("Failed to append INFO3 (NDR): %s\n",
    773                                 nt_errstr(result)));
    774                         return result;
    775                 }
    776         }
    777 
    778         if (flags & WBFLAG_PAM_UNIX_NAME) {
    779                 result = append_unix_username(state->mem_ctx, state, info3,
    780                                               name_domain, name_user);
    781                 if (!NT_STATUS_IS_OK(result)) {
    782                         DEBUG(10,("Failed to append Unix Username: %s\n",
    783                                 nt_errstr(result)));
    784                         return result;
    785                 }
    786         }
    787 
    788         if (flags & WBFLAG_PAM_AFS_TOKEN) {
    789                 result = append_afs_token(state->mem_ctx, state, info3,
    790                                           name_domain, name_user);
     773        if (request_flags & WBFLAG_PAM_AFS_TOKEN) {
     774                result = append_afs_token(mem_ctx, resp,
     775                                          info3, name_domain, name_user);
    791776                if (!NT_STATUS_IS_OK(result)) {
    792777                        DEBUG(10,("Failed to append AFS token: %s\n",
     
    799784}
    800785
    801 void winbindd_pam_auth(struct winbindd_cli_state *state)
    802 {
    803         struct winbindd_domain *domain;
    804         fstring name_domain, name_user;
    805         char *mapped = NULL;
    806         NTSTATUS result;
    807         NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL;
    808 
    809         /* Ensure null termination */
    810         state->request->data.auth.user
    811                 [sizeof(state->request->data.auth.user)-1]='\0';
    812 
    813         /* Ensure null termination */
    814         state->request->data.auth.pass
    815                 [sizeof(state->request->data.auth.pass)-1]='\0';
    816 
    817         DEBUG(3, ("[%5lu]: pam auth %s\n", (unsigned long)state->pid,
    818                   state->request->data.auth.user));
    819 
    820         if (!check_request_flags(state->request->flags)) {
    821                 result = NT_STATUS_INVALID_PARAMETER_MIX;
    822                 goto done;
    823         }
    824 
    825         /* Parse domain and username */
    826 
    827         name_map_status = normalize_name_unmap(state->mem_ctx,
    828                                                state->request->data.auth.user,
    829                                                &mapped);
    830 
    831         /* Update the auth name if we did any mapping */
    832 
    833         if (NT_STATUS_IS_OK(name_map_status) ||
    834             NT_STATUS_EQUAL(name_map_status, NT_STATUS_FILE_RENAMED))
    835         {
    836                 fstrcpy(state->request->data.auth.user, mapped);
    837         }
    838 
    839         if (!canonicalize_username(state->request->data.auth.user, name_domain, name_user)) {
    840                 result = NT_STATUS_NO_SUCH_USER;
    841                 goto done;
    842         }
    843 
    844         domain = find_auth_domain(state->request->flags, name_domain);
    845 
    846         if (domain == NULL) {
    847                 result = NT_STATUS_NO_SUCH_USER;
    848                 goto done;
    849         }
    850 
    851         sendto_domain(state, domain);
    852         return;
    853  done:
    854         set_auth_errors(state->response, result);
    855         DEBUG(5, ("Plain text authentication for %s returned %s "
    856                   "(PAM: %d)\n",
    857                   state->request->data.auth.user,
    858                   state->response->data.auth.nt_status_string,
    859                   state->response->data.auth.pam_error));
    860         request_error(state);
    861 }
    862 
    863786static NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain,
    864787                                              struct winbindd_cli_state *state,
     
    868791        uint16 max_allowed_bad_attempts;
    869792        fstring name_domain, name_user;
    870         DOM_SID sid;
     793        struct dom_sid sid;
    871794        enum lsa_SidType type;
    872795        uchar new_nt_pass[NT_HASH_LEN];
     
    891814
    892815
    893         if (!lookup_cached_name(state->mem_ctx,
    894                                 name_domain,
     816        if (!lookup_cached_name(name_domain,
    895817                                name_user,
    896818                                &sid,
     
    998920                        const char *principal_s = NULL;
    999921                        const char *service = NULL;
    1000                         bool internal_ccache = false;
    1001 
    1002                         uid = get_uid_from_state(state);
     922                        const char *user_ccache_file;
     923
     924                        uid = get_uid_from_request(state->request);
    1003925                        if (uid == -1) {
    1004926                                DEBUG(0,("winbindd_dual_pam_auth_cached: invalid uid\n"));
     
    1009931                                                state->request->data.auth.krb5_cc_type,
    1010932                                                state->request->data.auth.uid,
    1011                                                 &internal_ccache);
     933                                                &user_ccache_file);
    1012934                        if (cc == NULL) {
    1013935                                return NT_STATUS_NO_MEMORY;
     
    1027949                        }
    1028950
    1029                         if (!internal_ccache) {
    1030 
    1031                                 setup_return_cc_name(state, cc);
     951                        if (user_ccache_file != NULL) {
     952
     953                                fstrcpy(state->response->data.auth.krb5ccname,
     954                                        user_ccache_file);
    1032955
    1033956                                result = add_ccache_to_list(principal_s,
     
    1058981
    1059982                result = winbindd_update_creds_by_info3(domain,
    1060                                                         state->mem_ctx,
    1061983                                                        state->request->data.auth.user,
    1062984                                                        state->request->data.auth.pass,
     
    11011023                }
    11021024
    1103                 if ((my_info3->base.rid != DOMAIN_USER_RID_ADMIN) ||
     1025                if ((my_info3->base.rid != DOMAIN_RID_ADMINISTRATOR) ||
    11041026                    (password_properties & DOMAIN_PASSWORD_LOCKOUT_ADMINS)) {
    11051027                        my_info3->base.acct_flags |= ACB_AUTOLOCK;
     
    11091031failed:
    11101032        result = winbindd_update_creds_by_info3(domain,
    1111                                                 state->mem_ctx,
    11121033                                                state->request->data.auth.user,
    11131034                                                NULL,
     
    11761097        }
    11771098try_login:
    1178         result = winbindd_raw_kerberos_login(contact_domain, state, info3);
     1099        result = winbindd_raw_kerberos_login(
     1100                state->mem_ctx, contact_domain,
     1101                state->request->data.auth.user,
     1102                state->request->data.auth.pass,
     1103                state->request->data.auth.krb5_cc_type,
     1104                get_uid_from_request(state->request),
     1105                info3, state->response->data.auth.krb5ccname);
    11791106done:
    11801107        return result;
    11811108}
    11821109
    1183 typedef NTSTATUS (*netlogon_fn_t)(struct rpc_pipe_client *cli,
    1184                                   TALLOC_CTX *mem_ctx,
    1185                                   uint32 logon_parameters,
    1186                                   const char *server,
    1187                                   const char *username,
    1188                                   const char *domain,
    1189                                   const char *workstation,
    1190                                   const uint8 chal[8],
    1191                                   uint16_t validation_level,
    1192                                   DATA_BLOB lm_response,
    1193                                   DATA_BLOB nt_response,
    1194                                   struct netr_SamInfo3 **info3);
    1195 
    1196 static NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain,
    1197                                                 struct winbindd_cli_state *state,
    1198                                                 struct netr_SamInfo3 **info3)
    1199 {
    1200 
    1201         struct rpc_pipe_client *netlogon_pipe;
    1202         uchar chal[8];
    1203         DATA_BLOB lm_resp;
    1204         DATA_BLOB nt_resp;
     1110static NTSTATUS winbindd_dual_auth_passdb(TALLOC_CTX *mem_ctx,
     1111                                          const char *domain, const char *user,
     1112                                          const DATA_BLOB *challenge,
     1113                                          const DATA_BLOB *lm_resp,
     1114                                          const DATA_BLOB *nt_resp,
     1115                                          struct netr_SamInfo3 **pinfo3)
     1116{
     1117        struct auth_usersupplied_info *user_info = NULL;
     1118        NTSTATUS status;
     1119
     1120        status = make_user_info(&user_info, user, user, domain, domain,
     1121                                global_myname(), lm_resp, nt_resp, NULL, NULL,
     1122                                NULL, AUTH_PASSWORD_RESPONSE);
     1123        if (!NT_STATUS_IS_OK(status)) {
     1124                DEBUG(10, ("make_user_info failed: %s\n", nt_errstr(status)));
     1125                return status;
     1126        }
     1127
     1128        /* We don't want any more mapping of the username */
     1129        user_info->mapped_state = True;
     1130
     1131        status = check_sam_security_info3(challenge, talloc_tos(), user_info,
     1132                                          pinfo3);
     1133        free_user_info(&user_info);
     1134        DEBUG(10, ("Authenticaticating user %s\\%s returned %s\n", domain,
     1135                   user, nt_errstr(status)));
     1136        return status;
     1137}
     1138
     1139static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain,
     1140                                            TALLOC_CTX *mem_ctx,
     1141                                            uint32_t logon_parameters,
     1142                                            const char *server,
     1143                                            const char *username,
     1144                                            const char *domainname,
     1145                                            const char *workstation,
     1146                                            const uint8_t chal[8],
     1147                                            DATA_BLOB lm_response,
     1148                                            DATA_BLOB nt_response,
     1149                                            struct netr_SamInfo3 **info3)
     1150{
    12051151        int attempts = 0;
    1206         unsigned char local_lm_response[24];
    1207         unsigned char local_nt_response[24];
    1208         struct winbindd_domain *contact_domain;
    1209         fstring name_domain, name_user;
    1210         bool retry;
     1152        bool retry = false;
    12111153        NTSTATUS result;
    1212         struct netr_SamInfo3 *my_info3 = NULL;
    1213 
    1214         *info3 = NULL;
    1215 
    1216         DEBUG(10,("winbindd_dual_pam_auth_samlogon\n"));
    1217 
    1218         /* Parse domain and username */
    1219 
    1220         parse_domain_user(state->request->data.auth.user, name_domain, name_user);
    1221 
    1222         /* do password magic */
    1223 
    1224 
    1225         generate_random_buffer(chal, 8);
    1226         if (lp_client_ntlmv2_auth()) {
    1227                 DATA_BLOB server_chal;
    1228                 DATA_BLOB names_blob;
    1229                 DATA_BLOB nt_response;
    1230                 DATA_BLOB lm_response;
    1231                 server_chal = data_blob_talloc(state->mem_ctx, chal, 8);
    1232 
    1233                 /* note that the 'workgroup' here is a best guess - we don't know
    1234                    the server's domain at this point.  The 'server name' is also
    1235                    dodgy...
    1236                 */
    1237                 names_blob = NTLMv2_generate_names_blob(state->mem_ctx, global_myname(), lp_workgroup());
    1238 
    1239                 if (!SMBNTLMv2encrypt(NULL, name_user, name_domain,
    1240                                       state->request->data.auth.pass,
    1241                                       &server_chal,
    1242                                       &names_blob,
    1243                                       &lm_response, &nt_response, NULL, NULL)) {
    1244                         data_blob_free(&names_blob);
    1245                         data_blob_free(&server_chal);
    1246                         DEBUG(0, ("winbindd_pam_auth: SMBNTLMv2encrypt() failed!\n"));
    1247                         result = NT_STATUS_NO_MEMORY;
    1248                         goto done;
    1249                 }
    1250                 data_blob_free(&names_blob);
    1251                 data_blob_free(&server_chal);
    1252                 lm_resp = data_blob_talloc(state->mem_ctx, lm_response.data,
    1253                                            lm_response.length);
    1254                 nt_resp = data_blob_talloc(state->mem_ctx, nt_response.data,
    1255                                            nt_response.length);
    1256                 data_blob_free(&lm_response);
    1257                 data_blob_free(&nt_response);
    1258 
    1259         } else {
    1260                 if (lp_client_lanman_auth()
    1261                     && SMBencrypt(state->request->data.auth.pass,
    1262                                   chal,
    1263                                   local_lm_response)) {
    1264                         lm_resp = data_blob_talloc(state->mem_ctx,
    1265                                                    local_lm_response,
    1266                                                    sizeof(local_lm_response));
    1267                 } else {
    1268                         lm_resp = data_blob_null;
    1269                 }
    1270                 SMBNTencrypt(state->request->data.auth.pass,
    1271                              chal,
    1272                              local_nt_response);
    1273 
    1274                 nt_resp = data_blob_talloc(state->mem_ctx,
    1275                                            local_nt_response,
    1276                                            sizeof(local_nt_response));
    1277         }
    1278 
    1279         /* what domain should we contact? */
    1280 
    1281         if ( IS_DC ) {
    1282                 if (!(contact_domain = find_domain_from_name(name_domain))) {
    1283                         DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n",
    1284                                   state->request->data.auth.user, name_domain, name_user, name_domain));
    1285                         result = NT_STATUS_NO_SUCH_USER;
    1286                         goto done;
    1287                 }
    1288 
    1289         } else {
    1290                 if (is_myname(name_domain)) {
    1291                         DEBUG(3, ("Authentication for domain %s (local domain to this server) not supported at this stage\n", name_domain));
    1292                         result =  NT_STATUS_NO_SUCH_USER;
    1293                         goto done;
    1294                 }
    1295 
    1296                 contact_domain = find_our_domain();
    1297         }
    1298 
    1299         /* check authentication loop */
    13001154
    13011155        do {
    1302                 netlogon_fn_t logon_fn;
    1303                 const struct cli_pipe_auth_data *auth;
     1156                struct rpc_pipe_client *netlogon_pipe;
     1157                const struct pipe_auth_data *auth;
    13041158                uint32_t neg_flags = 0;
    13051159
    1306                 ZERO_STRUCTP(my_info3);
     1160                ZERO_STRUCTP(info3);
    13071161                retry = false;
    13081162
    1309                 result = cm_connect_netlogon(contact_domain, &netlogon_pipe);
     1163                result = cm_connect_netlogon(domain, &netlogon_pipe);
    13101164
    13111165                if (!NT_STATUS_IS_OK(result)) {
    1312                         DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
    1313                         goto done;
     1166                        DEBUG(3,("could not open handle to NETLOGON pipe (error: %s)\n",
     1167                                  nt_errstr(result)));
     1168                        return result;
    13141169                }
    13151170                auth = netlogon_pipe->auth;
     
    13481203                 * NETLOGON_NEG_AUTHENTICATED_RPC set together
    13491204                 * are the indication that the server supports
    1350                  * NetlogonValidationSamInfo4 (6). And must only
     1205                 * NetlogonValidationSamInfo4 (6). And it must only
    13511206                 * be used if "SealSecureChannel" is used.
    13521207                 *
     
    13561211                if (auth == NULL) {
    13571212                        domain->can_do_validation6 = false;
    1358                 } else if (auth->auth_type != PIPE_AUTH_TYPE_SCHANNEL) {
     1213                } else if (auth->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
    13591214                        domain->can_do_validation6 = false;
    13601215                } else if (auth->auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
     
    13661221                }
    13671222
    1368                 logon_fn = contact_domain->can_do_samlogon_ex
    1369                         ? rpccli_netlogon_sam_network_logon_ex
    1370                         : rpccli_netlogon_sam_network_logon;
    1371 
    1372                 result = logon_fn(netlogon_pipe,
    1373                                   state->mem_ctx,
    1374                                   0,
    1375                                   contact_domain->dcname, /* server name */
    1376                                   name_user,              /* user name */
    1377                                   name_domain,            /* target domain */
    1378                                   global_myname(),        /* workstation */
    1379                                   chal,
    1380                                   domain->can_do_validation6 ? 6 : 3,
    1381                                   lm_resp,
    1382                                   nt_resp,
    1383                                   &my_info3);
    1384 
    1385                 if ((NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR)
    1386                     && contact_domain->can_do_samlogon_ex) {
    1387                         DEBUG(3, ("Got a DC that can not do NetSamLogonEx, "
    1388                                   "retrying with NetSamLogon\n"));
    1389                         contact_domain->can_do_samlogon_ex = false;
     1223                if (domain->can_do_samlogon_ex) {
     1224                        result = rpccli_netlogon_sam_network_logon_ex(
     1225                                        netlogon_pipe,
     1226                                        mem_ctx,
     1227                                        0,
     1228                                        server,         /* server name */
     1229                                        username,       /* user name */
     1230                                        domainname,     /* target domain */
     1231                                        workstation,    /* workstation */
     1232                                        chal,
     1233                                        domain->can_do_validation6 ? 6 : 3,
     1234                                        lm_response,
     1235                                        nt_response,
     1236                                        info3);
     1237                } else {
     1238                        result = rpccli_netlogon_sam_network_logon(
     1239                                        netlogon_pipe,
     1240                                        mem_ctx,
     1241                                        0,
     1242                                        server,         /* server name */
     1243                                        username,       /* user name */
     1244                                        domainname,     /* target domain */
     1245                                        workstation,    /* workstation */
     1246                                        chal,
     1247                                        domain->can_do_validation6 ? 6 : 3,
     1248                                        lm_response,
     1249                                        nt_response,
     1250                                        info3);
     1251                }
     1252
     1253                if (NT_STATUS_EQUAL(result, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
     1254
    13901255                        /*
    13911256                         * It's likely that the server also does not support
     
    13931258                         */
    13941259                        domain->can_do_validation6 = false;
    1395                         retry = true;
    1396                         continue;
     1260
     1261                        if (domain->can_do_samlogon_ex) {
     1262                                DEBUG(3, ("Got a DC that can not do NetSamLogonEx, "
     1263                                          "retrying with NetSamLogon\n"));
     1264                                domain->can_do_samlogon_ex = false;
     1265                                retry = true;
     1266                                continue;
     1267                        }
     1268
     1269
     1270                        /* Got DCERPC_FAULT_OP_RNG_ERROR for SamLogon
     1271                         * (no Ex). This happens against old Samba
     1272                         * DCs. Drop the connection.
     1273                         */
     1274                        invalidate_cm_connection(&domain->conn);
     1275                        result = NT_STATUS_LOGON_FAILURE;
     1276                        break;
    13971277                }
    13981278
     
    14331313                                "password was changed and we didn't know it. "
    14341314                                 "Killing connections to domain %s\n",
    1435                                 name_domain));
    1436                         invalidate_cm_connection(&contact_domain->conn);
     1315                                domainname));
     1316                        invalidate_cm_connection(&domain->conn);
    14371317                        retry = true;
    14381318                }
    14391319
    14401320        } while ( (attempts < 2) && retry );
     1321
     1322        return result;
     1323}
     1324
     1325static NTSTATUS winbindd_dual_pam_auth_samlogon(TALLOC_CTX *mem_ctx,
     1326                                                struct winbindd_domain *domain,
     1327                                                const char *user,
     1328                                                const char *pass,
     1329                                                uint32_t request_flags,
     1330                                                struct netr_SamInfo3 **info3)
     1331{
     1332
     1333        uchar chal[8];
     1334        DATA_BLOB lm_resp;
     1335        DATA_BLOB nt_resp;
     1336        unsigned char local_nt_response[24];
     1337        fstring name_domain, name_user;
     1338        NTSTATUS result;
     1339        struct netr_SamInfo3 *my_info3 = NULL;
     1340
     1341        *info3 = NULL;
     1342
     1343        DEBUG(10,("winbindd_dual_pam_auth_samlogon\n"));
     1344
     1345        /* Parse domain and username */
     1346
     1347        parse_domain_user(user, name_domain, name_user);
     1348
     1349        /* do password magic */
     1350
     1351        generate_random_buffer(chal, sizeof(chal));
     1352
     1353        if (lp_client_ntlmv2_auth()) {
     1354                DATA_BLOB server_chal;
     1355                DATA_BLOB names_blob;
     1356                server_chal = data_blob_const(chal, 8);
     1357
     1358                /* note that the 'workgroup' here is for the local
     1359                   machine.  The 'server name' must match the
     1360                   'workstation' passed to the actual SamLogon call.
     1361                */
     1362                names_blob = NTLMv2_generate_names_blob(
     1363                        mem_ctx, global_myname(), lp_workgroup());
     1364
     1365                if (!SMBNTLMv2encrypt(mem_ctx, name_user, name_domain,
     1366                                      pass,
     1367                                      &server_chal,
     1368                                      &names_blob,
     1369                                      &lm_resp, &nt_resp, NULL, NULL)) {
     1370                        data_blob_free(&names_blob);
     1371                        DEBUG(0, ("winbindd_pam_auth: SMBNTLMv2encrypt() failed!\n"));
     1372                        result = NT_STATUS_NO_MEMORY;
     1373                        goto done;
     1374                }
     1375                data_blob_free(&names_blob);
     1376        } else {
     1377                lm_resp = data_blob_null;
     1378                SMBNTencrypt(pass, chal, local_nt_response);
     1379
     1380                nt_resp = data_blob_talloc(mem_ctx, local_nt_response,
     1381                                           sizeof(local_nt_response));
     1382        }
     1383
     1384        if (strequal(name_domain, get_global_sam_name())) {
     1385                DATA_BLOB chal_blob = data_blob_const(chal, sizeof(chal));
     1386
     1387                result = winbindd_dual_auth_passdb(
     1388                        mem_ctx, name_domain, name_user,
     1389                        &chal_blob, &lm_resp, &nt_resp, info3);
     1390                goto done;
     1391        }
     1392
     1393        /* check authentication loop */
     1394
     1395        result = winbind_samlogon_retry_loop(domain,
     1396                                             mem_ctx,
     1397                                             0,
     1398                                             domain->dcname,
     1399                                             name_user,
     1400                                             name_domain,
     1401                                             global_myname(),
     1402                                             chal,
     1403                                             lm_resp,
     1404                                             nt_resp,
     1405                                             &my_info3);
     1406        if (!NT_STATUS_IS_OK(result)) {
     1407                goto done;
     1408        }
    14411409
    14421410        /* handle the case where a NT4 DC does not fill in the acct_flags in
     
    14441412         * caller, we look up the account flags ourselve - gd */
    14451413
    1446         if ((state->request->flags & WBFLAG_PAM_INFO3_TEXT) &&
     1414        if ((request_flags & WBFLAG_PAM_INFO3_TEXT) &&
    14471415            NT_STATUS_IS_OK(result) && (my_info3->base.acct_flags == 0)) {
    14481416
     
    14501418                struct policy_handle samr_domain_handle, user_pol;
    14511419                union samr_UserInfo *info = NULL;
    1452                 NTSTATUS status_tmp;
     1420                NTSTATUS status_tmp, result_tmp;
    14531421                uint32 acct_flags;
    1454 
    1455                 status_tmp = cm_connect_sam(contact_domain, state->mem_ctx,
     1422                struct dcerpc_binding_handle *b;
     1423
     1424                status_tmp = cm_connect_sam(domain, mem_ctx,
    14561425                                            &samr_pipe, &samr_domain_handle);
    14571426
     
    14621431                }
    14631432
    1464                 status_tmp = rpccli_samr_OpenUser(samr_pipe, state->mem_ctx,
     1433                b = samr_pipe->binding_handle;
     1434
     1435                status_tmp = dcerpc_samr_OpenUser(b, mem_ctx,
    14651436                                                  &samr_domain_handle,
    14661437                                                  MAXIMUM_ALLOWED_ACCESS,
    14671438                                                  my_info3->base.rid,
    1468                                                   &user_pol);
     1439                                                  &user_pol,
     1440                                                  &result_tmp);
    14691441
    14701442                if (!NT_STATUS_IS_OK(status_tmp)) {
     
    14731445                        goto done;
    14741446                }
    1475 
    1476                 status_tmp = rpccli_samr_QueryUserInfo(samr_pipe, state->mem_ctx,
     1447                if (!NT_STATUS_IS_OK(result_tmp)) {
     1448                        DEBUG(3, ("could not open user handle on SAMR pipe: %s\n",
     1449                                nt_errstr(result_tmp)));
     1450                        goto done;
     1451                }
     1452
     1453                status_tmp = dcerpc_samr_QueryUserInfo(b, mem_ctx,
    14771454                                                       &user_pol,
    14781455                                                       16,
    1479                                                        &info);
     1456                                                       &info,
     1457                                                       &result_tmp);
    14801458
    14811459                if (!NT_STATUS_IS_OK(status_tmp)) {
    14821460                        DEBUG(3, ("could not query user info on SAMR pipe: %s\n",
    14831461                                nt_errstr(status_tmp)));
    1484                         rpccli_samr_Close(samr_pipe, state->mem_ctx, &user_pol);
     1462                        dcerpc_samr_Close(b, mem_ctx, &user_pol, &result_tmp);
    14851463                        goto done;
    14861464                }
     1465                if (!NT_STATUS_IS_OK(result_tmp)) {
     1466                        DEBUG(3, ("could not query user info on SAMR pipe: %s\n",
     1467                                nt_errstr(result_tmp)));
     1468                        dcerpc_samr_Close(b, mem_ctx, &user_pol, &result_tmp);
     1469                        goto done;
     1470                }
    14871471
    14881472                acct_flags = info->info16.acct_flags;
    14891473
    14901474                if (acct_flags == 0) {
    1491                         rpccli_samr_Close(samr_pipe, state->mem_ctx, &user_pol);
     1475                        dcerpc_samr_Close(b, mem_ctx, &user_pol, &result_tmp);
    14921476                        goto done;
    14931477                }
     
    14971481                DEBUG(10,("successfully retrieved acct_flags 0x%x\n", acct_flags));
    14981482
    1499                 rpccli_samr_Close(samr_pipe, state->mem_ctx, &user_pol);
     1483                dcerpc_samr_Close(b, mem_ctx, &user_pol, &result_tmp);
    15001484        }
    15011485
     
    15251509                  state->request->data.auth.user));
    15261510
    1527         if (!check_request_flags(state->request->flags)) {
    1528                 result = NT_STATUS_INVALID_PARAMETER_MIX;
    1529                 goto done;
    1530         }
    1531 
    15321511        /* Parse domain and username */
    15331512
     
    15481527
    15491528        if ( mapped_user != state->request->data.auth.user ) {
    1550                 fstr_sprintf( domain_user, "%s\\%s", name_domain, name_user );
     1529                fstr_sprintf( domain_user, "%s%c%s", name_domain,
     1530                        *lp_winbind_separator(),
     1531                        name_user );
    15511532                safe_strcpy( state->request->data.auth.user, domain_user,
    15521533                             sizeof(state->request->data.auth.user)-1 );
    15531534        }
    15541535
    1555         if (domain->online == false) {
     1536        if (!domain->online) {
    15561537                result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
    15571538                if (domain->startup) {
     
    16071588                    NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_MUST_CHANGE) ||
    16081589                    NT_STATUS_EQUAL(result, NT_STATUS_WRONG_PASSWORD)) {
    1609                         goto process_result;
     1590                        goto done;
    16101591                }
    16111592
     
    16211602        /* Check for Samlogon authentication */
    16221603        if (domain->online) {
    1623                 result = winbindd_dual_pam_auth_samlogon(domain, state, &info3);
     1604                result = winbindd_dual_pam_auth_samlogon(
     1605                        state->mem_ctx, domain,
     1606                        state->request->data.auth.user,
     1607                        state->request->data.auth.pass,
     1608                        state->request->flags,
     1609                        &info3);
    16241610
    16251611                if (NT_STATUS_IS_OK(result)) {
     
    16701656        if (NT_STATUS_IS_OK(result)) {
    16711657
    1672                 DOM_SID user_sid;
     1658                struct dom_sid user_sid;
    16731659
    16741660                /* In all codepaths where result == NT_STATUS_OK info3 must have
     
    16791665                }
    16801666
    1681                 wcache_invalidate_samlogon(find_domain_from_name(name_domain), info3);
     1667                sid_compose(&user_sid, info3->base.domain_sid,
     1668                            info3->base.rid);
     1669
     1670                wcache_invalidate_samlogon(find_domain_from_name(name_domain),
     1671                                           &user_sid);
    16821672                netsamlogon_cache_store(name_user, info3);
    16831673
     
    16871677                   domain). */
    16881678                if ( domain->primary ) {
    1689                         sid_compose(&user_sid, info3->base.domain_sid,
    1690                                     info3->base.rid);
    16911679                        cache_name2sid(domain, name_domain, name_user,
    16921680                                       SID_NAME_USER, &user_sid);
     
    17051693                }
    17061694
    1707                 result = append_auth_data(state, info3, name_domain,
    1708                                           name_user);
     1695                result = append_auth_data(state->mem_ctx, state->response,
     1696                                          state->request->flags, info3,
     1697                                          name_domain, name_user);
    17091698                if (!NT_STATUS_IS_OK(result)) {
    17101699                        goto done;
    17111700                }
    17121701
    1713                 if ((state->request->flags & WBFLAG_PAM_CACHED_LOGIN)) {
    1714 
    1715                         /* Store in-memory creds for single-signon using ntlm_auth. */
    1716                         result = winbindd_add_memory_creds(state->request->data.auth.user,
    1717                                                         get_uid_from_state(state),
    1718                                                         state->request->data.auth.pass);
    1719 
    1720                         if (!NT_STATUS_IS_OK(result)) {
    1721                                 DEBUG(10,("Failed to store memory creds: %s\n", nt_errstr(result)));
    1722                                 goto done;
    1723                         }
    1724 
    1725                         if (lp_winbind_offline_logon()) {
    1726                                 result = winbindd_store_creds(domain,
    1727                                                       state->mem_ctx,
     1702                if ((state->request->flags & WBFLAG_PAM_CACHED_LOGIN)
     1703                    && lp_winbind_offline_logon()) {
     1704
     1705                        result = winbindd_store_creds(domain,
    17281706                                                      state->request->data.auth.user,
    17291707                                                      state->request->data.auth.pass,
    1730                                                       info3, NULL);
    1731                                 if (!NT_STATUS_IS_OK(result)) {
    1732 
    1733                                         /* Release refcount. */
    1734                                         winbindd_delete_memory_creds(state->request->data.auth.user);
    1735 
    1736                                         DEBUG(10,("Failed to store creds: %s\n", nt_errstr(result)));
    1737                                         goto done;
    1738                                 }
    1739                         }
    1740                 }
    1741 
     1708                                                      info3);
     1709                }
    17421710
    17431711                if (state->request->flags & WBFLAG_PAM_GET_PWD_POLICY) {
     
    17521720                        result = NT_STATUS_NOT_SUPPORTED;
    17531721                        if (our_domain == domain ) {
    1754                                 result = fillup_password_policy(our_domain, state);
     1722                                result = fillup_password_policy(
     1723                                        our_domain, state->response);
    17551724                        }
    17561725
     
    17841753}
    17851754
    1786 
    1787 /**********************************************************************
    1788  Challenge Response Authentication Protocol
    1789 **********************************************************************/
    1790 
    1791 void winbindd_pam_auth_crap(struct winbindd_cli_state *state)
    1792 {
    1793         struct winbindd_domain *domain = NULL;
    1794         const char *domain_name = NULL;
    1795         NTSTATUS result;
    1796 
    1797         if (!check_request_flags(state->request->flags)) {
    1798                 result = NT_STATUS_INVALID_PARAMETER_MIX;
    1799                 goto done;
    1800         }
    1801 
    1802         if (!state->privileged) {
    1803                 DEBUG(2, ("winbindd_pam_auth_crap: non-privileged access "
    1804                           "denied.  !\n"));
    1805                 DEBUGADD(2, ("winbindd_pam_auth_crap: Ensure permissions "
    1806                              "on %s are set correctly.\n",
    1807                              get_winbind_priv_pipe_dir()));
    1808                 /* send a better message than ACCESS_DENIED */
    1809                 fstr_sprintf(state->response->data.auth.error_string,
    1810                              "winbind client not authorized to use "
    1811                              "winbindd_pam_auth_crap. Ensure permissions on "
    1812                              "%s are set correctly.",
    1813                              get_winbind_priv_pipe_dir());
    1814                 result = NT_STATUS_ACCESS_DENIED;
    1815                 goto done;
    1816         }
    1817 
    1818         /* Ensure null termination */
    1819         state->request->data.auth_crap.user
    1820                 [sizeof(state->request->data.auth_crap.user)-1]=0;
    1821         state->request->data.auth_crap.domain
    1822                 [sizeof(state->request->data.auth_crap.domain)-1]=0;
    1823 
    1824         DEBUG(3, ("[%5lu]: pam auth crap domain: [%s] user: %s\n",
    1825                   (unsigned long)state->pid,
    1826                   state->request->data.auth_crap.domain,
    1827                   state->request->data.auth_crap.user));
    1828 
    1829         if (*state->request->data.auth_crap.domain != '\0') {
    1830                 domain_name = state->request->data.auth_crap.domain;
    1831         } else if (lp_winbind_use_default_domain()) {
    1832                 domain_name = lp_workgroup();
    1833         }
    1834 
    1835         if (domain_name != NULL)
    1836                 domain = find_auth_domain(state->request->flags, domain_name);
    1837 
    1838         if (domain != NULL) {
    1839                 sendto_domain(state, domain);
    1840                 return;
    1841         }
    1842 
    1843         result = NT_STATUS_NO_SUCH_USER;
    1844 
    1845  done:
    1846         set_auth_errors(state->response, result);
    1847         DEBUG(5, ("CRAP authentication for %s\\%s returned %s (PAM: %d)\n",
    1848                   state->request->data.auth_crap.domain,
    1849                   state->request->data.auth_crap.user,
    1850                   state->response->data.auth.nt_status_string,
    1851                   state->response->data.auth.pam_error));
    1852         request_error(state);
    1853         return;
    1854 }
    1855 
    1856 
    18571755enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain,
    18581756                                                 struct winbindd_cli_state *state)
     
    18601758        NTSTATUS result;
    18611759        struct netr_SamInfo3 *info3 = NULL;
    1862         struct rpc_pipe_client *netlogon_pipe;
    18631760        const char *name_user = NULL;
    18641761        const char *name_domain = NULL;
    18651762        const char *workstation;
    1866         struct winbindd_domain *contact_domain;
    1867         int attempts = 0;
    1868         bool retry;
    18691763
    18701764        DATA_BLOB lm_resp, nt_resp;
     
    18771771        state->request->data.auth_crap.domain[sizeof(state->request->data.auth_crap.domain)-1]=0;
    18781772
    1879         if (!check_request_flags(state->request->flags)) {
    1880                 result = NT_STATUS_INVALID_PARAMETER_MIX;
    1881                 goto done;
    1882         }
    1883 
    18841773        name_user = state->request->data.auth_crap.user;
    1885 
    1886         if (*state->request->data.auth_crap.domain) {
    1887                 name_domain = state->request->data.auth_crap.domain;
    1888         } else if (lp_winbind_use_default_domain()) {
    1889                 name_domain = lp_workgroup();
    1890         } else {
    1891                 DEBUG(5,("no domain specified with username (%s) - failing auth\n",
    1892                          name_user));
    1893                 result = NT_STATUS_NO_SUCH_USER;
    1894                 goto done;
    1895         }
     1774        name_domain = state->request->data.auth_crap.domain;
     1775        workstation = state->request->data.auth_crap.workstation;
    18961776
    18971777        DEBUG(3, ("[%5lu]: pam auth crap domain: %s user: %s\n", (unsigned long)state->pid,
    18981778                  name_domain, name_user));
    1899 
    1900         if (*state->request->data.auth_crap.workstation) {
    1901                 workstation = state->request->data.auth_crap.workstation;
    1902         } else {
    1903                 workstation = global_myname();
    1904         }
    19051779
    19061780        if (state->request->data.auth_crap.lm_resp_len > sizeof(state->request->data.auth_crap.lm_resp)
     
    19291803        }
    19301804
    1931         /* what domain should we contact? */
    1932 
    1933         if ( IS_DC ) {
    1934                 if (!(contact_domain = find_domain_from_name(name_domain))) {
    1935                         DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n",
    1936                                   state->request->data.auth_crap.user, name_domain, name_user, name_domain));
    1937                         result = NT_STATUS_NO_SUCH_USER;
    1938                         goto done;
    1939                 }
    1940         } else {
    1941                 if (is_myname(name_domain)) {
    1942                         DEBUG(3, ("Authentication for domain %s (local domain to this server) not supported at this stage\n", name_domain));
    1943                         result =  NT_STATUS_NO_SUCH_USER;
    1944                         goto done;
    1945                 }
    1946                 contact_domain = find_our_domain();
    1947         }
    1948 
    1949         do {
    1950                 netlogon_fn_t logon_fn;
    1951                 const struct cli_pipe_auth_data *auth;
    1952                 uint32_t neg_flags = 0;
    1953 
    1954                 retry = false;
    1955 
    1956                 netlogon_pipe = NULL;
    1957                 result = cm_connect_netlogon(contact_domain, &netlogon_pipe);
    1958 
    1959                 if (!NT_STATUS_IS_OK(result)) {
    1960                         DEBUG(3, ("could not open handle to NETLOGON pipe (error: %s)\n",
    1961                                   nt_errstr(result)));
    1962                         goto done;
    1963                 }
    1964                 auth = netlogon_pipe->auth;
    1965                 if (netlogon_pipe->dc) {
    1966                         neg_flags = netlogon_pipe->dc->negotiate_flags;
    1967                 }
    1968 
    1969                 if (auth == NULL) {
    1970                         domain->can_do_validation6 = false;
    1971                 } else if (auth->auth_type != PIPE_AUTH_TYPE_SCHANNEL) {
    1972                         domain->can_do_validation6 = false;
    1973                 } else if (auth->auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
    1974                         domain->can_do_validation6 = false;
    1975                 } else if (!(neg_flags & NETLOGON_NEG_CROSS_FOREST_TRUSTS)) {
    1976                         domain->can_do_validation6 = false;
    1977                 } else if (!(neg_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) {
    1978                         domain->can_do_validation6 = false;
    1979                 }
    1980 
    1981                 logon_fn = contact_domain->can_do_samlogon_ex
    1982                         ? rpccli_netlogon_sam_network_logon_ex
    1983                         : rpccli_netlogon_sam_network_logon;
    1984 
    1985                 result = logon_fn(netlogon_pipe,
    1986                                   state->mem_ctx,
    1987                                   state->request->data.auth_crap.logon_parameters,
    1988                                   contact_domain->dcname,
    1989                                   name_user,
    1990                                   name_domain,
    1991                                   /* Bug #3248 - found by Stefan Burkei. */
    1992                                   workstation, /* We carefully set this above so use it... */
    1993                                   state->request->data.auth_crap.chal,
    1994                                   domain->can_do_validation6 ? 6 : 3,
    1995                                   lm_resp,
    1996                                   nt_resp,
    1997                                   &info3);
    1998 
    1999                 if ((NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR)
    2000                     && contact_domain->can_do_samlogon_ex) {
    2001                         DEBUG(3, ("Got a DC that can not do NetSamLogonEx, "
    2002                                   "retrying with NetSamLogon\n"));
    2003                         contact_domain->can_do_samlogon_ex = false;
    2004                         /*
    2005                          * It's likely that the server also does not support
    2006                          * validation level 6
    2007                          */
    2008                         domain->can_do_validation6 = false;
    2009                         retry = true;
    2010                         continue;
    2011                 }
    2012 
    2013                 if (domain->can_do_validation6 &&
    2014                     (NT_STATUS_EQUAL(result, NT_STATUS_INVALID_INFO_CLASS) ||
    2015                      NT_STATUS_EQUAL(result, NT_STATUS_INVALID_PARAMETER) ||
    2016                      NT_STATUS_EQUAL(result, NT_STATUS_BUFFER_TOO_SMALL))) {
    2017                         DEBUG(3,("Got a DC that can not do validation level 6, "
    2018                                   "retrying with level 3\n"));
    2019                         domain->can_do_validation6 = false;
    2020                         retry = true;
    2021                         continue;
    2022                 }
    2023 
    2024                 /*
    2025                  * we increment this after the "feature negotiation"
    2026                  * for can_do_samlogon_ex and can_do_validation6
    2027                  */
    2028                 attempts += 1;
    2029 
    2030                 /* We have to try a second time as cm_connect_netlogon
    2031                    might not yet have noticed that the DC has killed
    2032                    our connection. */
    2033 
    2034                 if (!rpccli_is_connected(netlogon_pipe)) {
    2035                         retry = true;
    2036                         continue;
    2037                 }
    2038 
    2039                 /* if we get access denied, a possible cause was that we had and open
    2040                    connection to the DC, but someone changed our machine account password
    2041                    out from underneath us using 'net rpc changetrustpw' */
    2042 
    2043                 if ( NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) ) {
    2044                         DEBUG(3,("winbindd_pam_auth: sam_logon returned "
    2045                                  "ACCESS_DENIED.  Maybe the trust account "
    2046                                 "password was changed and we didn't know it. "
    2047                                  "Killing connections to domain %s\n",
    2048                                 name_domain));
    2049                         invalidate_cm_connection(&contact_domain->conn);
    2050                         retry = true;
    2051                 }
    2052 
    2053         } while ( (attempts < 2) && retry );
     1805        if (strequal(name_domain, get_global_sam_name())) {
     1806                DATA_BLOB chal_blob = data_blob_const(
     1807                        state->request->data.auth_crap.chal,
     1808                        sizeof(state->request->data.auth_crap.chal));
     1809
     1810                result = winbindd_dual_auth_passdb(
     1811                        state->mem_ctx, name_domain, name_user,
     1812                        &chal_blob, &lm_resp, &nt_resp, &info3);
     1813                goto process_result;
     1814        }
     1815
     1816        result = winbind_samlogon_retry_loop(domain,
     1817                                             state->mem_ctx,
     1818                                             state->request->data.auth_crap.logon_parameters,
     1819                                             domain->dcname,
     1820                                             name_user,
     1821                                             name_domain,
     1822                                             /* Bug #3248 - found by Stefan Burkei. */
     1823                                             workstation, /* We carefully set this above so use it... */
     1824                                             state->request->data.auth_crap.chal,
     1825                                             lm_resp,
     1826                                             nt_resp,
     1827                                             &info3);
     1828        if (!NT_STATUS_IS_OK(result)) {
     1829                goto done;
     1830        }
     1831
     1832process_result:
    20541833
    20551834        if (NT_STATUS_IS_OK(result)) {
    2056 
    2057                 wcache_invalidate_samlogon(find_domain_from_name(name_domain), info3);
     1835                struct dom_sid user_sid;
     1836
     1837                sid_compose(&user_sid, info3->base.domain_sid,
     1838                            info3->base.rid);
     1839                wcache_invalidate_samlogon(find_domain_from_name(name_domain),
     1840                                           &user_sid);
    20581841                netsamlogon_cache_store(name_user, info3);
    20591842
     
    20711854                }
    20721855
    2073                 result = append_auth_data(state, info3, name_domain,
    2074                                           name_user);
     1856                result = append_auth_data(state->mem_ctx, state->response,
     1857                                          state->request->flags, info3,
     1858                                          name_domain, name_user);
    20751859                if (!NT_STATUS_IS_OK(result)) {
    20761860                        goto done;
     
    21021886}
    21031887
    2104 /* Change a user password */
    2105 
    2106 void winbindd_pam_chauthtok(struct winbindd_cli_state *state)
    2107 {
    2108         fstring domain, user;
    2109         char *mapped_user;
    2110         struct winbindd_domain *contact_domain;
    2111         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
    2112 
    2113         DEBUG(3, ("[%5lu]: pam chauthtok %s\n", (unsigned long)state->pid,
    2114                 state->request->data.chauthtok.user));
    2115 
    2116         /* Setup crap */
    2117 
    2118         nt_status = normalize_name_unmap(state->mem_ctx,
    2119                                          state->request->data.chauthtok.user,
    2120                                          &mapped_user);
    2121 
    2122         /* Update the chauthtok name if we did any mapping */
    2123 
    2124         if (NT_STATUS_IS_OK(nt_status) ||
    2125             NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_RENAMED))
    2126         {
    2127                 fstrcpy(state->request->data.chauthtok.user, mapped_user);
    2128         }
    2129 
    2130         /* Must pass in state->...chauthtok.user because
    2131            canonicalize_username() assumes an fstring().  Since
    2132            we have already copied it (if necessary), this is ok. */
    2133 
    2134         if (!canonicalize_username(state->request->data.chauthtok.user, domain, user)) {
    2135                 set_auth_errors(state->response, NT_STATUS_NO_SUCH_USER);
    2136                 DEBUG(5, ("winbindd_pam_chauthtok: canonicalize_username %s failed with %s"
    2137                           "(PAM: %d)\n",
    2138                           state->request->data.auth.user,
    2139                           state->response->data.auth.nt_status_string,
    2140                           state->response->data.auth.pam_error));
    2141                 request_error(state);
    2142                 return;
    2143         }
    2144 
    2145         contact_domain = find_domain_from_name(domain);
    2146         if (!contact_domain) {
    2147                 set_auth_errors(state->response, NT_STATUS_NO_SUCH_USER);
    2148                 DEBUG(3, ("Cannot change password for [%s] -> [%s]\\[%s] as %s is not a trusted domain\n",
    2149                           state->request->data.chauthtok.user, domain, user, domain));
    2150                 request_error(state);
    2151                 return;
    2152         }
    2153 
    2154         sendto_domain(state, contact_domain);
    2155 }
    2156 
    21571888enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact_domain,
    21581889                                                 struct winbindd_cli_state *state)
     
    21611892        char *newpass = NULL;
    21621893        struct policy_handle dom_pol;
    2163         struct rpc_pipe_client *cli;
     1894        struct rpc_pipe_client *cli = NULL;
    21641895        bool got_info = false;
    21651896        struct samr_DomInfo1 *info = NULL;
    2166         struct samr_ChangeReject *reject = NULL;
     1897        struct userPwdChangeFailureInformation *reject = NULL;
    21671898        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
    21681899        fstring domain, user;
     1900        struct dcerpc_binding_handle *b = NULL;
     1901
     1902        ZERO_STRUCT(dom_pol);
    21691903
    21701904        DEBUG(3, ("[%5lu]: dual pam chauthtok %s\n", (unsigned long)state->pid,
     
    21911925                goto done;
    21921926        }
     1927
     1928        b = cli->binding_handle;
    21931929
    21941930        result = rpccli_samr_chgpasswd_user3(cli, state->mem_ctx,
     
    22061942
    22071943                state->response->data.auth.reject_reason =
    2208                         reject->reason;
     1944                        reject->extendedFailureReason;
    22091945
    22101946                got_info = true;
     
    22171953
    22181954        /* only fallback when the chgpasswd_user3 call is not supported */
    2219         if ((NT_STATUS_EQUAL(result, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR))) ||
    2220                    (NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED)) ||
    2221                    (NT_STATUS_EQUAL(result, NT_STATUS_BUFFER_TOO_SMALL)) ||
    2222                    (NT_STATUS_EQUAL(result, NT_STATUS_NOT_IMPLEMENTED))) {
     1955        if (NT_STATUS_EQUAL(result, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE) ||
     1956            NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED) ||
     1957            NT_STATUS_EQUAL(result, NT_STATUS_BUFFER_TOO_SMALL) ||
     1958            NT_STATUS_EQUAL(result, NT_STATUS_NOT_IMPLEMENTED)) {
    22231959
    22241960                DEBUG(10,("Password change with chgpasswd_user3 failed with: %s, retrying chgpasswd_user2\n",
     
    22371973done:
    22381974
    2239         if (NT_STATUS_IS_OK(result) && (state->request->flags & WBFLAG_PAM_CACHED_LOGIN)) {
    2240 
    2241                 /* Update the single sign-on memory creds. */
    2242                 result = winbindd_replace_memory_creds(state->request->data.chauthtok.user,
    2243                                                         newpass);
    2244 
    2245                 /* When we login from gdm or xdm and password expires,
    2246                  * we change password, but there are no memory crendentials
    2247                  * So, winbindd_replace_memory_creds() returns
    2248                  * NT_STATUS_OBJECT_NAME_NOT_FOUND. This is not a failure.
     1975        if (NT_STATUS_IS_OK(result)
     1976            && (state->request->flags & WBFLAG_PAM_CACHED_LOGIN)
     1977            && lp_winbind_offline_logon()) {
     1978                result = winbindd_update_creds_by_name(contact_domain, user,
     1979                                                       newpass);
     1980                /* Again, this happens when we login from gdm or xdm
     1981                 * and the password expires, *BUT* cached crendentials
     1982                 * doesn't exist. winbindd_update_creds_by_name()
     1983                 * returns NT_STATUS_NO_SUCH_USER.
     1984                 * This is not a failure.
    22491985                 * --- BoYang
    22501986                 * */
    2251                 if (NT_STATUS_EQUAL(result, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
     1987                if (NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_USER)) {
    22521988                        result = NT_STATUS_OK;
    22531989                }
    22541990
    22551991                if (!NT_STATUS_IS_OK(result)) {
    2256                         DEBUG(10,("Failed to replace memory creds: %s\n", nt_errstr(result)));
     1992                        DEBUG(10, ("Failed to store creds: %s\n",
     1993                                   nt_errstr(result)));
    22571994                        goto process_result;
    22581995                }
    2259 
    2260                 if (lp_winbind_offline_logon()) {
    2261                         result = winbindd_update_creds_by_name(contact_domain,
    2262                                                          state->mem_ctx, user,
    2263                                                          newpass);
    2264                         /* Again, this happens when we login from gdm or xdm
    2265                          * and the password expires, *BUT* cached crendentials
    2266                          * doesn't exist. winbindd_update_creds_by_name()
    2267                          * returns NT_STATUS_NO_SUCH_USER.
    2268                          * This is not a failure.
    2269                          * --- BoYang
    2270                          * */
    2271                         if (NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_USER)) {
    2272                                 result = NT_STATUS_OK;
    2273                         }
    2274 
    2275                         if (!NT_STATUS_IS_OK(result)) {
    2276                                 DEBUG(10,("Failed to store creds: %s\n", nt_errstr(result)));
    2277                                 goto process_result;
    2278                         }
    2279                 }
    22801996        }
    22811997
     
    22842000                NTSTATUS policy_ret;
    22852001
    2286                 policy_ret = fillup_password_policy(contact_domain, state);
     2002                policy_ret = fillup_password_policy(
     2003                        contact_domain, state->response);
    22872004
    22882005                /* failure of this is non critical, it will just provide no
     
    22972014
    22982015process_result:
     2016
     2017        if (strequal(contact_domain->name, get_global_sam_name())) {
     2018                /* FIXME: internal rpc pipe does not cache handles yet */
     2019                if (b) {
     2020                        if (is_valid_policy_hnd(&dom_pol)) {
     2021                                NTSTATUS _result;
     2022                                dcerpc_samr_Close(b, state->mem_ctx, &dom_pol, &_result);
     2023                        }
     2024                        TALLOC_FREE(cli);
     2025                }
     2026        }
    22992027
    23002028        set_auth_errors(state->response, result);
     
    23102038}
    23112039
    2312 void winbindd_pam_logoff(struct winbindd_cli_state *state)
    2313 {
    2314         struct winbindd_domain *domain;
    2315         fstring name_domain, user;
    2316         uid_t caller_uid = (uid_t)-1;
    2317         uid_t request_uid = state->request->data.logoff.uid;
    2318 
    2319         DEBUG(3, ("[%5lu]: pam logoff %s\n", (unsigned long)state->pid,
    2320                 state->request->data.logoff.user));
    2321 
    2322         /* Ensure null termination */
    2323         state->request->data.logoff.user
    2324                 [sizeof(state->request->data.logoff.user)-1]='\0';
    2325 
    2326         state->request->data.logoff.krb5ccname
    2327                 [sizeof(state->request->data.logoff.krb5ccname)-1]='\0';
    2328 
    2329         if (request_uid == (gid_t)-1) {
    2330                 goto failed;
    2331         }
    2332 
    2333         if (!canonicalize_username(state->request->data.logoff.user, name_domain, user)) {
    2334                 goto failed;
    2335         }
    2336 
    2337         if ((domain = find_auth_domain(state->request->flags,
    2338                                        name_domain)) == NULL) {
    2339                 goto failed;
    2340         }
    2341 
    2342         if ((sys_getpeereid(state->sock, &caller_uid)) != 0) {
    2343                 DEBUG(1,("winbindd_pam_logoff: failed to check peerid: %s\n",
    2344                         strerror(errno)));
    2345                 goto failed;
    2346         }
    2347 
    2348         switch (caller_uid) {
    2349                 case -1:
    2350                         goto failed;
    2351                 case 0:
    2352                         /* root must be able to logoff any user - gd */
    2353                         state->request->data.logoff.uid = request_uid;
    2354                         break;
    2355                 default:
    2356                         if (caller_uid != request_uid) {
    2357                                 DEBUG(1,("winbindd_pam_logoff: caller requested invalid uid\n"));
    2358                                 goto failed;
    2359                         }
    2360                         state->request->data.logoff.uid = caller_uid;
    2361                         break;
    2362         }
    2363 
    2364         sendto_domain(state, domain);
    2365         return;
    2366 
    2367  failed:
    2368         set_auth_errors(state->response, NT_STATUS_NO_SUCH_USER);
    2369         DEBUG(5, ("Pam Logoff for %s returned %s "
    2370                   "(PAM: %d)\n",
    2371                   state->request->data.logoff.user,
    2372                   state->response->data.auth.nt_status_string,
    2373                   state->response->data.auth.pam_error));
    2374         request_error(state);
    2375         return;
    2376 }
    2377 
    23782040enum winbindd_result winbindd_dual_pam_logoff(struct winbindd_domain *domain,
    23792041                                              struct winbindd_cli_state *state)
     
    24302092process_result:
    24312093
    2432         winbindd_delete_memory_creds(state->request->data.logoff.user);
    24332094
    24342095        set_auth_errors(state->response, result);
     
    24382099
    24392100/* Change user password with auth crap*/
    2440 
    2441 void winbindd_pam_chng_pswd_auth_crap(struct winbindd_cli_state *state)
    2442 {
    2443         struct winbindd_domain *domain = NULL;
    2444         const char *domain_name = NULL;
    2445 
    2446         /* Ensure null termination */
    2447         state->request->data.chng_pswd_auth_crap.user[
    2448                 sizeof(state->request->data.chng_pswd_auth_crap.user)-1]=0;
    2449         state->request->data.chng_pswd_auth_crap.domain[
    2450                 sizeof(state->request->data.chng_pswd_auth_crap.domain)-1]=0;
    2451 
    2452         DEBUG(3, ("[%5lu]: pam change pswd auth crap domain: %s user: %s\n",
    2453                   (unsigned long)state->pid,
    2454                   state->request->data.chng_pswd_auth_crap.domain,
    2455                   state->request->data.chng_pswd_auth_crap.user));
    2456 
    2457         if (*state->request->data.chng_pswd_auth_crap.domain != '\0') {
    2458                 domain_name = state->request->data.chng_pswd_auth_crap.domain;
    2459         } else if (lp_winbind_use_default_domain()) {
    2460                 domain_name = lp_workgroup();
    2461         }
    2462 
    2463         if (domain_name != NULL)
    2464                 domain = find_domain_from_name(domain_name);
    2465 
    2466         if (domain != NULL) {
    2467                 DEBUG(7, ("[%5lu]: pam auth crap changing pswd in domain: "
    2468                           "%s\n", (unsigned long)state->pid,domain->name));
    2469                 sendto_domain(state, domain);
    2470                 return;
    2471         }
    2472 
    2473         set_auth_errors(state->response, NT_STATUS_NO_SUCH_USER);
    2474         DEBUG(5, ("CRAP change password  for %s\\%s returned %s (PAM: %d)\n",
    2475                   state->request->data.chng_pswd_auth_crap.domain,
    2476                   state->request->data.chng_pswd_auth_crap.user,
    2477                   state->response->data.auth.nt_status_string,
    2478                   state->response->data.auth.pam_error));
    2479         request_error(state);
    2480         return;
    2481 }
    24822101
    24832102enum winbindd_result winbindd_dual_pam_chng_pswd_auth_crap(struct winbindd_domain *domainSt, struct winbindd_cli_state *state)
     
    24912110        struct policy_handle dom_pol;
    24922111        struct winbindd_domain *contact_domain = domainSt;
    2493         struct rpc_pipe_client *cli;
     2112        struct rpc_pipe_client *cli = NULL;
     2113        struct dcerpc_binding_handle *b = NULL;
     2114
     2115        ZERO_STRUCT(dom_pol);
    24942116
    24952117        /* Ensure null termination */
     
    25402162
    25412163        /* Change password */
    2542         new_nt_password = data_blob_talloc(
    2543                 state->mem_ctx,
     2164        new_nt_password = data_blob_const(
    25442165                state->request->data.chng_pswd_auth_crap.new_nt_pswd,
    25452166                state->request->data.chng_pswd_auth_crap.new_nt_pswd_len);
    25462167
    2547         old_nt_hash_enc = data_blob_talloc(
    2548                 state->mem_ctx,
     2168        old_nt_hash_enc = data_blob_const(
    25492169                state->request->data.chng_pswd_auth_crap.old_nt_hash_enc,
    25502170                state->request->data.chng_pswd_auth_crap.old_nt_hash_enc_len);
    25512171
    25522172        if(state->request->data.chng_pswd_auth_crap.new_lm_pswd_len > 0)        {
    2553                 new_lm_password = data_blob_talloc(
    2554                         state->mem_ctx,
     2173                new_lm_password = data_blob_const(
    25552174                        state->request->data.chng_pswd_auth_crap.new_lm_pswd,
    25562175                        state->request->data.chng_pswd_auth_crap.new_lm_pswd_len);
    25572176
    2558                 old_lm_hash_enc = data_blob_talloc(
    2559                         state->mem_ctx,
     2177                old_lm_hash_enc = data_blob_const(
    25602178                        state->request->data.chng_pswd_auth_crap.old_lm_hash_enc,
    25612179                        state->request->data.chng_pswd_auth_crap.old_lm_hash_enc_len);
     
    25732191        }
    25742192
     2193        b = cli->binding_handle;
     2194
    25752195        result = rpccli_samr_chng_pswd_auth_crap(
    25762196                cli, state->mem_ctx, user, new_nt_password, old_nt_hash_enc,
     
    25782198
    25792199 done:
     2200
     2201        if (strequal(contact_domain->name, get_global_sam_name())) {
     2202                /* FIXME: internal rpc pipe does not cache handles yet */
     2203                if (b) {
     2204                        if (is_valid_policy_hnd(&dom_pol)) {
     2205                                NTSTATUS _result;
     2206                                dcerpc_samr_Close(b, state->mem_ctx, &dom_pol, &_result);
     2207                        }
     2208                        TALLOC_FREE(cli);
     2209                }
     2210        }
    25802211
    25812212        set_auth_errors(state->response, result);
Note: See TracChangeset for help on using the changeset viewer.