The attached file contains an extension to the SAMBA authentication
subsystem to support PAULA pass-through authentication. PAULA is
defined in the ActiveX/DCOM specification, at the following URL:

        http://www.opengroup.org/onlinepubs/009899899

It should be refactored as a dynamically loadable plugin -- I am
told that this is trivial to do.

Note, though, that the present implementation does not encrypt
sensitive parameters with a shared secret, as required by the
specification. In our implementation, we needed a simple way of
allowing SAMBA to authenticate NTLM clients against our own DCE
RPC-based domain controller (on the same host), and wished to
avoid the configuration overhead of a shared secret. We only
accept PAULA requests that come from a trusted client on the
local machine.

-- Luke
/* 
   Unix SMB/CIFS implementation.

   PAULA authentication implementation

   Copyright (C) Luke Howard 2002
   
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "includes.h"

#include <paula.h>

#undef DBGC_CLASS
#define DBGC_CLASS DBGC_AUTH

/*
 * PAULA, or the Private AUthentication LAyer, is an interface for 
 * doing NTLM authentication on machines that don't have a fully-
 * fleged LSA (eg. Unix systems).
 *
 * The interface is defined by Microsoft and Compaq in the DCOM
 * specification available at:
 *   http://www.opengroup.org/onlinepubs/009899899/CHP01CHP.HTM#chap01.sect1.5
 */

static NTSTATUS check_paula_security(const struct auth_context *auth_context,
                                       void *my_private_data, 
                                       TALLOC_CTX *mem_ctx,
                                       const auth_usersupplied_info *user_info, 
                                       auth_serversupplied_info **server_info)
{
        char Domain[64];
        char Workstation[64];
        char UserName[64];
        char Challenge[8];
        char CaseInsensitiveChallengeResponse[24];
        char CaseSensitiveChallengeResponse[24];
        char UserSessionKey[16];
        char LanManSessionKey[8];
        unsigned32 Cookie;
        NTSTATUS status;
        unsigned32 protocolStatus, protocolSubStatus;

        if (user_info == NULL) {
                return NT_STATUS_INVALID_PARAMETER;
        }

        if (auth_context == NULL) {
                DEBUG(3, ("check_paula_security: no authentication context provided 
for user %s\n", user_info->internal_username.str));
                return NT_STATUS_UNSUCCESSFUL;
        }

        if (user_info->domain.len >= sizeof(Domain)) {
                return NT_STATUS_BUFFER_TOO_SMALL;
        }
        memcpy(Domain, user_info->domain.str, user_info->domain.len + 1);

        if (user_info->wksta_name.len >= sizeof(Workstation)) {
                return NT_STATUS_BUFFER_TOO_SMALL;
        }
        memcpy(Workstation, user_info->wksta_name.str, user_info->wksta_name.len + 1);

        if (user_info->smb_name.len >= sizeof(UserName)) {
                return NT_STATUS_BUFFER_TOO_SMALL;
        }
        memcpy(UserName, user_info->smb_name.str, user_info->smb_name.len + 1);

        if (auth_context->challenge.length > sizeof(Challenge)) {
                return NT_STATUS_BUFFER_TOO_SMALL;
        }
        memcpy(Challenge, auth_context->challenge.data, 
auth_context->challenge.length);

        if (user_info->lm_resp.length > sizeof(CaseInsensitiveChallengeResponse)) {
                return NT_STATUS_BUFFER_TOO_SMALL;
        }
        memcpy(CaseInsensitiveChallengeResponse, user_info->lm_resp.data, 
user_info->lm_resp.length);

        if (user_info->nt_resp.length > sizeof(CaseSensitiveChallengeResponse)) {
                return NT_STATUS_BUFFER_TOO_SMALL;
        }
        memcpy(CaseSensitiveChallengeResponse, user_info->nt_resp.data, 
user_info->nt_resp.length);

        PaulaLMLogonRequest(Cookie,
                Domain,
                Workstation,
                UserName,
                Challenge,
                CaseInsensitiveChallengeResponse,
                CaseSensitiveChallengeResponse,
                &Cookie,
                &protocolStatus,
                &protocolSubStatus,
                (unsigned32 *)&status,
                UserSessionKey,
                LanManSessionKey);
        if (protocolStatus != 0) {
                DEBUG(1, ("check_paula_security: PaulaLMLogonRequest RPC failed (%08x 
%08x)\n", protocolStatus, protocolSubStatus));
                return NT_STATUS_UNSUCCESSFUL;
        }

        DEBUG(1, ("check_paula_security: PaulaLMLogonRequest returned %08x\n", 
status));

        if (NT_STATUS_IS_OK(status)) {
                struct passwd *pwd;

                pwd = Get_Pwnam(UserName);
                if (pwd == NULL) {
                        DEBUG(1, ("check_paula_security: could not find local account 
for %s\n", UserName));
                        status = NT_STATUS_NO_SUCH_USER;
                } else {
                        make_server_info_pw(server_info, pwd);
                }
        }

        return status;
}

/* module initialisation */
NTSTATUS auth_init_paula(struct auth_context *auth_context, const char *param, 
auth_methods **auth_method) 
{
        if (!make_auth_methods(auth_context, auth_method)) {
                return NT_STATUS_NO_MEMORY;
        }

        (*auth_method)->name = "paula";
        (*auth_method)->auth = check_paula_security;
        return NT_STATUS_OK;
}
--
Luke Howard | PADL Software Pty Ltd | www.padl.com

Reply via email to