mirror of
https://github.com/samba-team/samba.git
synced 2024-12-27 03:21:53 +03:00
587cf54c61
(This used to be commit fd34ce4370
)
240 lines
4.9 KiB
C
240 lines
4.9 KiB
C
/*
|
|
* Unix SMB/CIFS implementation.
|
|
* Generate AFS tickets
|
|
* Copyright (C) Volker Lendecke 2004
|
|
*
|
|
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "includes.h"
|
|
|
|
#ifdef WITH_FAKE_KASERVER
|
|
|
|
#define NO_ASN1_TYPEDEFS 1
|
|
|
|
#include <afs/stds.h>
|
|
#include <afs/afs.h>
|
|
#include <afs/auth.h>
|
|
#include <afs/venus.h>
|
|
#include <asm/unistd.h>
|
|
#include <openssl/des.h>
|
|
#include <sys/syscall.h>
|
|
|
|
int afs_syscall( int subcall,
|
|
char * path,
|
|
int cmd,
|
|
char * cmarg,
|
|
int follow)
|
|
{
|
|
return( syscall( SYS_afs_syscall, subcall, path, cmd, cmarg, follow));
|
|
}
|
|
|
|
struct ClearToken {
|
|
uint32 AuthHandle;
|
|
char HandShakeKey[8];
|
|
uint32 ViceId;
|
|
uint32 BeginTimestamp;
|
|
uint32 EndTimestamp;
|
|
};
|
|
|
|
static bool afs_decode_token(const char *string, char **cell,
|
|
DATA_BLOB *ticket, struct ClearToken *ct)
|
|
{
|
|
DATA_BLOB blob;
|
|
struct ClearToken result_ct;
|
|
char *saveptr;
|
|
|
|
char *s = SMB_STRDUP(string);
|
|
|
|
char *t;
|
|
|
|
if ((t = strtok_r(s, "\n", &saveptr)) == NULL) {
|
|
DEBUG(10, ("strtok_r failed\n"));
|
|
return False;
|
|
}
|
|
|
|
*cell = SMB_STRDUP(t);
|
|
|
|
if ((t = strtok_r(NULL, "\n", &saveptr)) == NULL) {
|
|
DEBUG(10, ("strtok_r failed\n"));
|
|
return False;
|
|
}
|
|
|
|
if (sscanf(t, "%u", &result_ct.AuthHandle) != 1) {
|
|
DEBUG(10, ("sscanf AuthHandle failed\n"));
|
|
return False;
|
|
}
|
|
|
|
if ((t = strtok_r(NULL, "\n", &saveptr)) == NULL) {
|
|
DEBUG(10, ("strtok_r failed\n"));
|
|
return False;
|
|
}
|
|
|
|
blob = base64_decode_data_blob(t);
|
|
|
|
if ( (blob.data == NULL) ||
|
|
(blob.length != sizeof(result_ct.HandShakeKey) )) {
|
|
DEBUG(10, ("invalid key: %x/%d\n", (uint32)blob.data,
|
|
blob.length));
|
|
return False;
|
|
}
|
|
|
|
memcpy(result_ct.HandShakeKey, blob.data, blob.length);
|
|
|
|
data_blob_free(&blob);
|
|
|
|
if ((t = strtok_r(NULL, "\n", &saveptr)) == NULL) {
|
|
DEBUG(10, ("strtok_r failed\n"));
|
|
return False;
|
|
}
|
|
|
|
if (sscanf(t, "%u", &result_ct.ViceId) != 1) {
|
|
DEBUG(10, ("sscanf ViceId failed\n"));
|
|
return False;
|
|
}
|
|
|
|
if ((t = strtok_r(NULL, "\n", &saveptr)) == NULL) {
|
|
DEBUG(10, ("strtok_r failed\n"));
|
|
return False;
|
|
}
|
|
|
|
if (sscanf(t, "%u", &result_ct.BeginTimestamp) != 1) {
|
|
DEBUG(10, ("sscanf BeginTimestamp failed\n"));
|
|
return False;
|
|
}
|
|
|
|
if ((t = strtok_r(NULL, "\n", &saveptr)) == NULL) {
|
|
DEBUG(10, ("strtok_r failed\n"));
|
|
return False;
|
|
}
|
|
|
|
if (sscanf(t, "%u", &result_ct.EndTimestamp) != 1) {
|
|
DEBUG(10, ("sscanf EndTimestamp failed\n"));
|
|
return False;
|
|
}
|
|
|
|
if ((t = strtok_r(NULL, "\n", &saveptr)) == NULL) {
|
|
DEBUG(10, ("strtok_r failed\n"));
|
|
return False;
|
|
}
|
|
|
|
blob = base64_decode_data_blob(t);
|
|
|
|
if (blob.data == NULL) {
|
|
DEBUG(10, ("Could not get ticket\n"));
|
|
return False;
|
|
}
|
|
|
|
*ticket = blob;
|
|
*ct = result_ct;
|
|
|
|
return True;
|
|
}
|
|
|
|
/*
|
|
Put an AFS token into the Kernel so that it can authenticate against
|
|
the AFS server. This assumes correct local uid settings.
|
|
|
|
This is currently highly Linux and OpenAFS-specific. The correct API
|
|
call for this would be ktc_SetToken. But to do that we would have to
|
|
import a REALLY big bunch of libraries which I would currently like
|
|
to avoid.
|
|
*/
|
|
|
|
static bool afs_settoken(const char *cell,
|
|
const struct ClearToken *ctok,
|
|
DATA_BLOB ticket)
|
|
{
|
|
int ret;
|
|
struct {
|
|
char *in, *out;
|
|
uint16 in_size, out_size;
|
|
} iob;
|
|
|
|
char buf[1024];
|
|
char *p = buf;
|
|
int tmp;
|
|
|
|
memcpy(p, &ticket.length, sizeof(uint32));
|
|
p += sizeof(uint32);
|
|
memcpy(p, ticket.data, ticket.length);
|
|
p += ticket.length;
|
|
|
|
tmp = sizeof(struct ClearToken);
|
|
memcpy(p, &tmp, sizeof(uint32));
|
|
p += sizeof(uint32);
|
|
memcpy(p, ctok, tmp);
|
|
p += tmp;
|
|
|
|
tmp = 0;
|
|
|
|
memcpy(p, &tmp, sizeof(uint32));
|
|
p += sizeof(uint32);
|
|
|
|
tmp = strlen(cell);
|
|
if (tmp >= MAXKTCREALMLEN) {
|
|
DEBUG(1, ("Realm too long\n"));
|
|
return False;
|
|
}
|
|
|
|
strncpy(p, cell, tmp);
|
|
p += tmp;
|
|
*p = 0;
|
|
p +=1;
|
|
|
|
iob.in = buf;
|
|
iob.in_size = PTR_DIFF(p,buf);
|
|
iob.out = buf;
|
|
iob.out_size = sizeof(buf);
|
|
|
|
#if 0
|
|
file_save("/tmp/ioctlbuf", iob.in, iob.in_size);
|
|
#endif
|
|
|
|
ret = afs_syscall(AFSCALL_PIOCTL, 0, VIOCSETTOK, (char *)&iob, 0);
|
|
|
|
DEBUG(10, ("afs VIOCSETTOK returned %d\n", ret));
|
|
return (ret == 0);
|
|
}
|
|
|
|
bool afs_settoken_str(const char *token_string)
|
|
{
|
|
DATA_BLOB ticket;
|
|
struct ClearToken ct;
|
|
bool result;
|
|
char *cell;
|
|
|
|
if (!afs_decode_token(token_string, &cell, &ticket, &ct))
|
|
return False;
|
|
|
|
if (geteuid() != 0)
|
|
ct.ViceId = getuid();
|
|
|
|
result = afs_settoken(cell, &ct, ticket);
|
|
|
|
SAFE_FREE(cell);
|
|
data_blob_free(&ticket);
|
|
|
|
return result;
|
|
}
|
|
|
|
#else
|
|
|
|
bool afs_settoken_str(const char *token_string)
|
|
{
|
|
return False;
|
|
}
|
|
|
|
#endif
|