Windows: Only Local System Account may set tokens for alternate ids

Only permit tokens to be set for alternate ids from the system
account.

LICENSE MIT

Change-Id: Ibeaf16950b0317db99dfebccb9534697a258db78
Reviewed-on: http://gerrit.openafs.org/2541
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Tested-by: Jeffrey Altman <jaltman@openafs.org>
Reviewed-by: Jeffrey Altman <jaltman@openafs.org>
This commit is contained in:
Jeffrey Altman 2010-08-12 01:48:16 -04:00 committed by Jeffrey Altman
parent 5e8d0a7b5f
commit 22f6306cc8
4 changed files with 89 additions and 7 deletions

View File

@ -138,6 +138,10 @@ extern const int utf8_prefix_size;
#define AFSCALL_RXSTATS_DISABLE 0x2 /* Disable RX stats */
#define AFSCALL_RXSTATS_CLEAR 0x4 /* Clear RX stats */
/* pioctl flags */
#define AFSCALL_FLAG_LOCAL_SYSTEM 0x1
#ifndef __CM_IOCTL_INTERFACES_ONLY__
extern void cm_InitIoctl(void);

View File

@ -15,6 +15,7 @@
#pragma warning(disable: 4005)
#include <ntstatus.h>
#pragma warning(pop)
#include <sddl.h>
#include <stddef.h>
#include <stdlib.h>
#include <malloc.h>
@ -1230,6 +1231,63 @@ smb_user_t *smb_FindUID(smb_vc_t *vcp, unsigned short uid, int flags)
return uidp;
}
afs_int32 smb_userIsLocalSystem(smb_user_t *uidp)
{
SID *pSid = NULL;
DWORD dwSize1 = 0, dwSize2 = 0;
wchar_t *pszRefDomain = NULL;
SID_NAME_USE snu = SidTypeGroup;
clientchar_t * secSidString = NULL;
DWORD gle;
afs_int32 isSystem = 0;
/*
* The input name is probably not a SID for the user which is how
* the user is now being identified as a result of the SMB
* extended authentication. See if we can obtain the SID for the
* specified name. If we can, use that instead of the name
* provided.
*/
LookupAccountNameW( NULL /* System Name to begin Search */,
uidp->unp->name,
NULL, &dwSize1,
NULL, &dwSize2,
&snu);
gle = GetLastError();
if (gle == ERROR_INSUFFICIENT_BUFFER) {
pSid = malloc(dwSize1);
/*
* Although dwSize2 is supposed to include the terminating
* NUL character, on Win7 it does not.
*/
pszRefDomain = malloc((dwSize2 + 1) * sizeof(wchar_t));
}
if ( pSid && pszRefDomain ) {
memset(pSid, 0, dwSize1);
if (LookupAccountNameW( NULL /* System Name to begin Search */,
uidp->unp->name,
pSid, &dwSize1,
pszRefDomain, &dwSize2,
&snu))
ConvertSidToStringSidW(pSid, &secSidString);
}
if (secSidString) {
isSystem = !cm_ClientStrCmp(NTSID_LOCAL_SYSTEM, secSidString);
LocalFree(secSidString);
}
if (pSid)
free(pSid);
if (pszRefDomain)
free(pszRefDomain);
return isSystem;
}
smb_username_t *smb_FindUserByName(clientchar_t *usern, clientchar_t *machine,
afs_uint32 flags)
{

View File

@ -170,6 +170,8 @@ typedef struct smb {
#define NTNEGOTIATE_CAPABILITY_COMPRESSED 0x40000000L
#define NTNEGOTIATE_CAPABILITY_EXTENDED_SECURITY 0x80000000L
#define NTSID_LOCAL_SYSTEM L"S-1-5-18"
/* a packet structure for receiving SMB messages; locked by smb_globalLock.
* Most of the work involved is in handling chained requests and responses.
*
@ -600,6 +602,8 @@ extern void smb_ReleaseTID(smb_tid_t *tidp, afs_uint32 locked);
extern smb_user_t *smb_FindUID(smb_vc_t *vcp, unsigned short uid, int flags);
extern afs_int32 smb_userIsLocalSystem(smb_user_t *userp);
extern smb_username_t *smb_FindUserByName(clientchar_t *usern, clientchar_t *machine, afs_uint32 flags);
extern cm_user_t *smb_FindCMUserByName(clientchar_t *usern, clientchar_t *machine, afs_uint32 flags);

View File

@ -205,21 +205,37 @@ smb_IoctlRead(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *o
afs_int32 leftToCopy;
char *op;
afs_int32 code;
cm_user_t *userp;
smb_user_t *uidp;
cm_user_t *userp = NULL;
smb_t *smbp;
int isSystem = 0;
iop = fidp->ioctlp;
count = smb_GetSMBParm(inp, 1);
userp = smb_GetUserFromVCP(vcp, inp);
/* Get the user and determine if it is the local machine account */
smbp = (smb_t *) inp;
uidp = smb_FindUID(vcp, smbp->uid, 0);
if (uidp) {
isSystem = smb_userIsLocalSystem(uidp);
userp = smb_GetUserFromUID(uidp);
smb_ReleaseUID(uidp);
}
if (!userp) {
userp = cm_rootUserp;
cm_HoldUser(userp);
}
/* Identify tree */
code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &iop->tidPathp);
if(code) {
if (code) {
cm_ReleaseUser(userp);
return CM_ERROR_NOSUCHPATH;
}
/* turn the connection around, if required */
code = smb_IoctlPrepareRead(fidp, iop, userp, 0);
code = smb_IoctlPrepareRead(fidp, iop, userp, isSystem ? AFSCALL_FLAG_LOCAL_SYSTEM : 0);
if (code) {
cm_ReleaseUser(userp);
@ -1016,7 +1032,7 @@ smb_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pf
uname = cm_ParseIoctlStringAlloc(&ioctlp->ioctl, tp);
tp += strlen(tp) + 1;
if (flags & PIOCTL_LOGON) {
if ((pflags & AFSCALL_FLAG_LOCAL_SYSTEM) && (flags & PIOCTL_LOGON)) {
/* SMB user name with which to associate tokens */
smbname = cm_ParseIoctlStringAlloc(&ioctlp->ioctl, tp);
osi_Log2(smb_logp,"cm_IoctlSetToken for user [%S] smbname [%S]",
@ -1040,7 +1056,7 @@ smb_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pf
osi_Log0(smb_logp,"cm_IoctlSetToken - no name specified");
}
if (flags & PIOCTL_LOGON) {
if ((pflags & AFSCALL_FLAG_LOCAL_SYSTEM) && (flags & PIOCTL_LOGON)) {
userp = smb_FindCMUserByName(smbname, ioctlp->fidp->vcp->rname,
SMB_FLAG_CREATE|SMB_FLAG_AFSLOGON);
release_userp = 1;
@ -1077,7 +1093,7 @@ smb_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pf
ucellp->flags |= CM_UCELLFLAG_RXKAD;
lock_ReleaseMutex(&userp->mx);
if (flags & PIOCTL_LOGON) {
if ((pflags & AFSCALL_FLAG_LOCAL_SYSTEM) && (flags & PIOCTL_LOGON)) {
ioctlp->ioctl.flags |= CM_IOCTLFLAG_LOGON;
}