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/auth/auth_netlogond.c

    r596 r745  
    1919
    2020#include "includes.h"
     21#include "auth.h"
    2122#include "../libcli/auth/libcli_auth.h"
     23#include "../librpc/gen_ndr/ndr_netlogon.h"
     24#include "librpc/gen_ndr/ndr_schannel.h"
     25#include "rpc_client/cli_pipe.h"
     26#include "rpc_client/cli_netlogon.h"
     27#include "secrets.h"
     28#include "tldap.h"
     29#include "tldap_util.h"
    2230
    2331#undef DBGC_CLASS
    2432#define DBGC_CLASS DBGC_AUTH
     33
     34static bool secrets_store_local_schannel_creds(
     35        const struct netlogon_creds_CredentialState *creds)
     36{
     37        DATA_BLOB blob;
     38        enum ndr_err_code ndr_err;
     39        bool ret;
     40
     41        ndr_err = ndr_push_struct_blob(
     42                &blob, talloc_tos(), creds,
     43                (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState);
     44        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     45                DEBUG(10, ("ndr_push_netlogon_creds_CredentialState failed: "
     46                           "%s\n", ndr_errstr(ndr_err)));
     47                return false;
     48        }
     49        ret = secrets_store(SECRETS_LOCAL_SCHANNEL_KEY,
     50                            blob.data, blob.length);
     51        data_blob_free(&blob);
     52        return ret;
     53}
     54
     55static struct netlogon_creds_CredentialState *
     56secrets_fetch_local_schannel_creds(TALLOC_CTX *mem_ctx)
     57{
     58        struct netlogon_creds_CredentialState *creds;
     59        enum ndr_err_code ndr_err;
     60        DATA_BLOB blob;
     61
     62        blob.data = (uint8_t *)secrets_fetch(SECRETS_LOCAL_SCHANNEL_KEY,
     63                                             &blob.length);
     64        if (blob.data == NULL) {
     65                DEBUG(10, ("secrets_fetch failed\n"));
     66                return NULL;
     67        }
     68
     69        creds = talloc(mem_ctx, struct netlogon_creds_CredentialState);
     70        if (creds == NULL) {
     71                DEBUG(10, ("talloc failed\n"));
     72                SAFE_FREE(blob.data);
     73                return NULL;
     74        }
     75        ndr_err = ndr_pull_struct_blob(
     76                &blob, creds, creds,
     77                (ndr_pull_flags_fn_t)ndr_pull_netlogon_creds_CredentialState);
     78        SAFE_FREE(blob.data);
     79        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     80                DEBUG(10, ("ndr_pull_netlogon_creds_CredentialState failed: "
     81                           "%s\n", ndr_errstr(ndr_err)));
     82                TALLOC_FREE(creds);
     83                return NULL;
     84        }
     85
     86        return creds;
     87}
    2588
    2689static NTSTATUS netlogond_validate(TALLOC_CTX *mem_ctx,
    2790                                   const struct auth_context *auth_context,
    2891                                   const char *ncalrpc_sockname,
    29                                    uint8_t schannel_key[16],
    30                                    const auth_usersupplied_info *user_info,
     92                                   struct netlogon_creds_CredentialState *creds,
     93                                   const struct auth_usersupplied_info *user_info,
    3194                                   struct netr_SamInfo3 **pinfo3,
    3295                                   NTSTATUS *schannel_bind_result)
    3396{
    3497        struct rpc_pipe_client *p = NULL;
    35         struct cli_pipe_auth_data *auth = NULL;
     98        struct pipe_auth_data *auth = NULL;
    3699        struct netr_SamInfo3 *info3 = NULL;
    37100        NTSTATUS status;
     
    47110        }
    48111
    49         /*
    50          * We have to fake a struct dcinfo, so that
    51          * rpccli_netlogon_sam_network_logon_ex can decrypt the session keys.
    52          */
    53 
    54         p->dc = netlogon_creds_client_init_session_key(p, schannel_key);
    55         if (p->dc == NULL) {
    56                 DEBUG(0, ("talloc failed\n"));
    57                 TALLOC_FREE(p);
    58                 return NT_STATUS_NO_MEMORY;
    59         }
     112        p->dc = creds;
    60113
    61114        status = rpccli_schannel_bind_data(p, lp_workgroup(),
     
    79132        status = rpccli_netlogon_sam_network_logon_ex(
    80133                p, p,
    81                 user_info->logon_parameters,/* flags such as 'allow
    82                                              * workstation logon' */
    83                 global_myname(),            /* server name */
    84                 user_info->smb_name,        /* user name logging on. */
    85                 user_info->client_domain,   /* domain name */
    86                 user_info->wksta_name,      /* workstation name */
     134                user_info->logon_parameters,           /* flags such as 'allow
     135                                                        * workstation logon' */
     136                global_myname(),                       /* server name */
     137                user_info->client.account_name,        /* user name logging on. */
     138                user_info->client.domain_name,         /* domain name */
     139                user_info->workstation_name,           /* workstation name */
    87140                (uchar *)auth_context->challenge.data, /* 8 byte challenge. */
    88                 3,                          /* validation level */
    89                 user_info->lm_resp,         /* lanman 24 byte response */
    90                 user_info->nt_resp,         /* nt 24 byte response */
    91                 &info3);                    /* info3 out */
     141                3,                                     /* validation level */
     142                user_info->password.response.lanman,   /* lanman 24 byte response */
     143                user_info->password.response.nt,       /* nt 24 byte response */
     144                &info3);                               /* info3 out */
    92145
    93146        DEBUG(10, ("rpccli_netlogon_sam_network_logon_ex returned %s\n",
     
    105158}
    106159
    107 static char *mymachinepw(TALLOC_CTX *mem_ctx)
    108 {
    109         fstring pwd;
    110         const char *script;
    111         char *to_free = NULL;
    112         ssize_t nread;
    113         int ret, fd;
    114 
    115         script = lp_parm_const_string(
    116                 GLOBAL_SECTION_SNUM, "auth_netlogond", "machinepwscript",
    117                 NULL);
    118 
    119         if (script == NULL) {
    120                 to_free = talloc_asprintf(talloc_tos(), "%s/%s",
    121                                           get_dyn_SBINDIR(), "mymachinepw");
    122                 script = to_free;
    123         }
    124         if (script == NULL) {
    125                 return NULL;
    126         }
    127 
    128         ret = smbrun(script, &fd);
    129         DEBUG(ret ? 0 : 3, ("mymachinepw: Running the command `%s' gave %d\n",
    130                             script, ret));
    131         TALLOC_FREE(to_free);
    132 
    133         if (ret != 0) {
    134                 return NULL;
    135         }
    136 
    137         nread = read(fd, pwd, sizeof(pwd)-1);
    138         close(fd);
    139 
    140         if (nread <= 0) {
    141                 DEBUG(3, ("mymachinepwd: Could not read password\n"));
    142                 return NULL;
    143         }
    144 
    145         pwd[nread] = '\0';
    146 
    147         if (pwd[nread-1] == '\n') {
    148                 pwd[nread-1] = '\0';
    149         }
    150 
    151         return talloc_strdup(mem_ctx, pwd);
     160static NTSTATUS get_ldapi_ctx(TALLOC_CTX *mem_ctx, struct tldap_context **pld)
     161{
     162        struct tldap_context *ld;
     163        struct sockaddr_un addr;
     164        char *sockaddr;
     165        int fd;
     166        NTSTATUS status;
     167        int res;
     168
     169        sockaddr = talloc_asprintf(talloc_tos(), "/%s/ldap_priv/ldapi",
     170                                   lp_private_dir());
     171        if (sockaddr == NULL) {
     172                DEBUG(10, ("talloc failed\n"));
     173                return NT_STATUS_NO_MEMORY;
     174        }
     175
     176        ZERO_STRUCT(addr);
     177        addr.sun_family = AF_UNIX;
     178        strncpy(addr.sun_path, sockaddr, sizeof(addr.sun_path));
     179        TALLOC_FREE(sockaddr);
     180
     181        status = open_socket_out((struct sockaddr_storage *)(void *)&addr,
     182                                 0, 0, &fd);
     183        if (!NT_STATUS_IS_OK(status)) {
     184                DEBUG(10, ("Could not connect to %s: %s\n", addr.sun_path,
     185                           nt_errstr(status)));
     186                return status;
     187        }
     188        set_blocking(fd, false);
     189
     190        ld = tldap_context_create(mem_ctx, fd);
     191        if (ld == NULL) {
     192                close(fd);
     193                return NT_STATUS_NO_MEMORY;
     194        }
     195        res = tldap_fetch_rootdse(ld);
     196        if (res != TLDAP_SUCCESS) {
     197                DEBUG(10, ("tldap_fetch_rootdse failed: %s\n",
     198                           tldap_errstr(talloc_tos(), ld, res)));
     199                TALLOC_FREE(ld);
     200                return NT_STATUS_LDAP(res);
     201        }
     202        *pld = ld;
     203        return NT_STATUS_OK;;
     204}
     205
     206static NTSTATUS mymachinepw(uint8_t pwd[16])
     207{
     208        TALLOC_CTX *frame = talloc_stackframe();
     209        struct tldap_context *ld = NULL;
     210        struct tldap_message *rootdse, **msg;
     211        const char *attrs[1] = { "unicodePwd" };
     212        char *default_nc, *myname;
     213        int rc, num_msg;
     214        DATA_BLOB pwdblob;
     215        NTSTATUS status;
     216
     217        status = get_ldapi_ctx(talloc_tos(), &ld);
     218        if (!NT_STATUS_IS_OK(status)) {
     219                goto fail;
     220        }
     221        rootdse = tldap_rootdse(ld);
     222        if (rootdse == NULL) {
     223                DEBUG(10, ("Could not get rootdse\n"));
     224                status = NT_STATUS_INTERNAL_ERROR;
     225                goto fail;
     226        }
     227        default_nc = tldap_talloc_single_attribute(
     228                rootdse, "defaultNamingContext", talloc_tos());
     229        if (default_nc == NULL) {
     230                DEBUG(10, ("Could not get defaultNamingContext\n"));
     231                status = NT_STATUS_NO_MEMORY;
     232                goto fail;
     233        }
     234        DEBUG(10, ("default_nc = %s\n", default_nc));
     235
     236        myname = talloc_asprintf_strupper_m(talloc_tos(), "%s$",
     237                                            global_myname());
     238        if (myname == NULL) {
     239                DEBUG(10, ("talloc failed\n"));
     240                status = NT_STATUS_NO_MEMORY;
     241                goto fail;
     242        }
     243
     244        rc = tldap_search_fmt(
     245                ld, default_nc, TLDAP_SCOPE_SUB, attrs, ARRAY_SIZE(attrs), 0,
     246                talloc_tos(), &msg,
     247                "(&(sAMAccountName=%s)(objectClass=computer))", myname);
     248        if (rc != TLDAP_SUCCESS) {
     249                DEBUG(10, ("Could not retrieve our account: %s\n",
     250                           tldap_errstr(talloc_tos(), ld, rc)));
     251                status = NT_STATUS_LDAP(rc);
     252                goto fail;
     253        }
     254        num_msg = talloc_array_length(msg);
     255        if (num_msg != 1) {
     256                DEBUG(10, ("Got %d accounts, expected one\n", num_msg));
     257                status = NT_STATUS_INTERNAL_DB_CORRUPTION;
     258                goto fail;
     259        }
     260        if (!tldap_get_single_valueblob(msg[0], "unicodePwd", &pwdblob)) {
     261                char *dn = NULL;
     262                tldap_entry_dn(msg[0], &dn);
     263                DEBUG(10, ("No unicodePwd attribute in %s\n",
     264                           dn ? dn : "<unknown DN>"));
     265                status = NT_STATUS_INTERNAL_DB_CORRUPTION;
     266                goto fail;
     267        }
     268        if (pwdblob.length != 16) {
     269                DEBUG(10, ("Password hash hash has length %d, expected 16\n",
     270                           (int)pwdblob.length));
     271                status = NT_STATUS_INTERNAL_DB_CORRUPTION;
     272                goto fail;
     273        }
     274        memcpy(pwd, pwdblob.data, 16);
     275
     276fail:
     277        TALLOC_FREE(frame);
     278        return status;
    152279}
    153280
     
    155282                                         void *my_private_data,
    156283                                         TALLOC_CTX *mem_ctx,
    157                                          const auth_usersupplied_info *user_info,
    158                                          auth_serversupplied_info **server_info)
     284                                         const struct auth_usersupplied_info *user_info,
     285                                         struct auth_serversupplied_info **server_info)
    159286{
    160287        TALLOC_CTX *frame = talloc_stackframe();
    161288        struct netr_SamInfo3 *info3 = NULL;
    162289        struct rpc_pipe_client *p = NULL;
    163         struct cli_pipe_auth_data *auth = NULL;
     290        struct pipe_auth_data *auth = NULL;
    164291        uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
    165         char *plaintext_machinepw = NULL;
    166292        uint8_t machine_password[16];
    167         uint8_t schannel_key[16];
     293        struct netlogon_creds_CredentialState *creds;
    168294        NTSTATUS schannel_bind_result, status;
    169295        struct named_mutex *mutex = NULL;
    170296        const char *ncalrpcsock;
    171297
     298        DEBUG(10, ("Check auth for: [%s]\n", user_info->mapped.account_name));
     299
    172300        ncalrpcsock = lp_parm_const_string(
    173301                GLOBAL_SECTION_SNUM, "auth_netlogond", "socket", NULL);
     
    183311        }
    184312
    185         if (!secrets_fetch_local_schannel_key(schannel_key)) {
     313        creds = secrets_fetch_local_schannel_creds(talloc_tos());
     314        if (creds == NULL) {
    186315                goto new_key;
    187316        }
    188317
    189318        status = netlogond_validate(talloc_tos(), auth_context, ncalrpcsock,
    190                                     schannel_key, user_info, &info3,
     319                                    creds, user_info, &info3,
    191320                                    &schannel_bind_result);
    192321
     
    237366        }
    238367
    239         plaintext_machinepw = mymachinepw(talloc_tos());
    240         if (plaintext_machinepw == NULL) {
    241                 status = NT_STATUS_NO_MEMORY;
    242                 goto done;
    243         }
    244 
    245         E_md4hash(plaintext_machinepw, machine_password);
    246 
    247         TALLOC_FREE(plaintext_machinepw);
     368        status = mymachinepw(machine_password);
     369        if (!NT_STATUS_IS_OK(status)) {
     370                DEBUG(10, ("mymachinepw failed: %s\n", nt_errstr(status)));
     371                goto done;
     372        }
     373
     374        DEBUG(10, ("machinepw "));
     375        dump_data(10, machine_password, 16);
    248376
    249377        status = rpccli_netlogon_setup_creds(
     
    257385        }
    258386
    259         memcpy(schannel_key, p->dc->session_key, 16);
    260         secrets_store_local_schannel_key(schannel_key);
    261 
    262         TALLOC_FREE(p);
     387        secrets_store_local_schannel_creds(p->dc);
    263388
    264389        /*
     
    268393
    269394        status = netlogond_validate(talloc_tos(), auth_context, ncalrpcsock,
    270                                     schannel_key, user_info, &info3,
     395                                    p->dc, user_info, &info3,
    271396                                    &schannel_bind_result);
    272397
     398        TALLOC_FREE(p);
     399
    273400        DEBUG(10, ("netlogond_validate returned %s\n", nt_errstr(status)));
    274401
     
    279406 okay:
    280407
    281         status = make_server_info_info3(mem_ctx, user_info->smb_name,
    282                                         user_info->domain, server_info,
     408        status = make_server_info_info3(mem_ctx, user_info->client.account_name,
     409                                        user_info->mapped.domain_name, server_info,
    283410                                        info3);
    284411        if (!NT_STATUS_IS_OK(status)) {
     
    301428                                    auth_methods **auth_method)
    302429{
    303         if (!make_auth_methods(auth_context, auth_method)) {
     430        struct auth_methods *result;
     431
     432        result = TALLOC_ZERO_P(auth_context, struct auth_methods);
     433        if (result == NULL) {
    304434                return NT_STATUS_NO_MEMORY;
    305435        }
    306 
    307         (*auth_method)->name = "netlogond";
    308         (*auth_method)->auth = check_netlogond_security;
     436        result->name = "netlogond";
     437        result->auth = check_netlogond_security;
     438
     439        *auth_method = result;
    309440        return NT_STATUS_OK;
    310441}
Note: See TracChangeset for help on using the changeset viewer.