Commit ef7f26cf authored by Guido Günther's avatar Guido Günther

New upstream version 1.1+svn10616

parent 96671997
=========================================================
PyKerberos Package
Copyright (c) 2006-2008 Apple Inc. All rights reserved.
Copyright (c) 2006-2013 Apple Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
......
##
# Copyright (c) 2006-2009 Apple Inc. All rights reserved.
# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
......@@ -99,7 +99,7 @@ GSS_C_ANON_FLAG = 64
GSS_C_PROT_READY_FLAG = 128
GSS_C_TRANS_FLAG = 256
def authGSSClientInit(service, gssflags=GSS_C_MUTUAL_FLAG|GSS_C_SEQUENCE_FLAG):
def authGSSClientInit(service, principal=None, gssflags=GSS_C_MUTUAL_FLAG|GSS_C_SEQUENCE_FLAG):
"""
Initializes a context for GSSAPI client-side authentication with the given service principal.
authGSSClientClean must be called after this function returns an OK result to dispose of
......@@ -107,6 +107,8 @@ def authGSSClientInit(service, gssflags=GSS_C_MUTUAL_FLAG|GSS_C_SEQUENCE_FLAG):
@param service: a string containing the service principal in the form 'type@fqdn'
(e.g. 'imap@mail.apple.com').
@param principal: optional string containing the client principal in the form 'user@realm'
(e.g. 'jdoe@example.com').
@param gssflags: optional integer used to set GSS flags.
(e.g. GSS_C_DELEG_FLAG|GSS_C_MUTUAL_FLAG|GSS_C_SEQUENCE_FLAG will allow
for forwarding credentials to the remote host)
......@@ -141,6 +143,14 @@ def authGSSClientResponse(context):
@return: a string containing the base64-encoded client data to be sent to the server.
"""
def authGSSClientResponseConf(context):
"""
Returns 1 if confidentiality was enabled in the previously unwrapped buffer. 0 otherwise.
@param context: the context object returned from authGSSClientInit.
@return: an integer representing the confidentiality of the previously unwrapped buffer.
"""
def authGSSClientUserName(context):
"""
Get the user name of the principal authenticated via the now complete GSSAPI client-side operations.
......@@ -158,12 +168,13 @@ def authGSSClientUnwrap(context, challenge):
@return: a result code (see above)
"""
def authGSSClientWrap(context, data, user=None):
def authGSSClientWrap(context, data, user=None, protect=0):
"""
Perform the client side GSSAPI wrap step.
@param data:the result of the authGSSClientResponse after the authGSSClientUnwrap
@param user: the user to authorize
@param protect: if 0 then just provide integrity protection, if 1, then provide confidentiality as well.
@return: a result code (see above)
"""
......
##
# Copyright (c) 2006-2008 Apple Inc. All rights reserved.
# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
......@@ -18,10 +18,25 @@ from distutils.core import setup, Extension
import sys
import commands
long_description = """
This Python package is a high-level wrapper for Kerberos (GSSAPI) operations.
The goal is to avoid having to build a module that wraps the entire Kerberos.framework,
and instead offer a limited set of functions that do what is needed for client/server
Kerberos authentication based on <http://www.ietf.org/rfc/rfc4559.txt>.
"""
setup (
name = "kerberos",
version = "1.0",
version = "1.1.1",
description = "Kerberos high-level interface",
long_description=long_description,
classifiers = [
"License :: OSI Approved :: Apache Software License",
"Programming Language :: Python :: 2",
"Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: System :: Systems Administration :: Authentication/Directory"
],
ext_modules = [
Extension(
"kerberos",
......
/**
* Copyright (c) 2006-2008 Apple Inc. All rights reserved.
* Copyright (c) 2006-2013 Apple Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -40,7 +40,7 @@ static signed char index_64[128] =
// value : data to encode
// vlen : length of data
// (result) : new char[] - c-str of result
char *base64_encode(const unsigned char *value, int vlen)
char *base64_encode(const unsigned char *value, size_t vlen)
{
char *result = (char *)malloc((vlen * 4) / 3 + 5);
char *out = result;
......@@ -72,12 +72,12 @@ char *base64_encode(const unsigned char *value, int vlen)
// value : c-str to decode
// rlen : length of decoded result
// (result) : new unsigned char[] - decoded result
unsigned char *base64_decode(const char *value, int *rlen)
unsigned char *base64_decode(const char *value, size_t *rlen)
{
*rlen = 0;
int c1, c2, c3, c4;
int vlen = strlen(value);
size_t vlen = strlen(value);
unsigned char *result =(unsigned char *)malloc((vlen * 3) / 4 + 1);
unsigned char *out = result;
......
/**
* Copyright (c) 2006-2008 Apple Inc. All rights reserved.
* Copyright (c) 2006-2013 Apple Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -14,5 +14,6 @@
* limitations under the License.
**/
char *base64_encode(const unsigned char *value, int vlen);
unsigned char *base64_decode(const char *value, int *rlen);
#include <stddef.h>
char *base64_encode(const unsigned char *value, size_t vlen);
unsigned char *base64_decode(const char *value, size_t *rlen);
/**
* Copyright (c) 2006-2009 Apple Inc. All rights reserved.
* Copyright (c) 2006-2013 Apple Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -27,10 +27,10 @@ PyObject *GssException_class;
static PyObject *checkPassword(PyObject *self, PyObject *args)
{
const char *user;
const char *pswd;
const char *service;
const char *default_realm;
const char *user = NULL;
const char *pswd = NULL;
const char *service = NULL;
const char *default_realm = NULL;
int result = 0;
if (!PyArg_ParseTuple(args, "ssss", &user, &pswd, &service, &default_realm))
......@@ -46,8 +46,9 @@ static PyObject *checkPassword(PyObject *self, PyObject *args)
static PyObject *changePassword(PyObject *self, PyObject *args)
{
const char *newpswd, *oldpswd;
const char *user;
const char *newpswd = NULL;
const char *oldpswd = NULL;
const char *user = NULL;
int result = 0;
if (!PyArg_ParseTuple(args, "sss", &user, &oldpswd, &newpswd))
......@@ -63,8 +64,8 @@ static PyObject *changePassword(PyObject *self, PyObject *args)
static PyObject *getServerPrincipalDetails(PyObject *self, PyObject *args)
{
const char *service;
const char *hostname;
const char *service = NULL;
const char *hostname = NULL;
char* result;
if (!PyArg_ParseTuple(args, "ss", &service, &hostname))
......@@ -84,20 +85,21 @@ static PyObject *getServerPrincipalDetails(PyObject *self, PyObject *args)
static PyObject* authGSSClientInit(PyObject* self, PyObject* args, PyObject* keywds)
{
const char *service;
const char *service = NULL;
const char *principal = NULL;
gss_client_state *state;
PyObject *pystate;
static char *kwlist[] = {"service", "gssflags", NULL};
static char *kwlist[] = {"service", "principal", "gssflags", NULL};
long int gss_flags = GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG;
int result = 0;
if (!PyArg_ParseTupleAndKeywords(args, keywds, "s|l", kwlist, &service, &gss_flags))
if (!PyArg_ParseTupleAndKeywords(args, keywds, "s|zl", kwlist, &service, &principal, &gss_flags))
return NULL;
state = (gss_client_state *) malloc(sizeof(gss_client_state));
pystate = PyCObject_FromVoidPtr(state, NULL);
result = authenticate_gss_client_init(service, gss_flags, state);
result = authenticate_gss_client_init(service, principal, gss_flags, state);
if (result == AUTH_GSS_ERROR)
return NULL;
......@@ -134,7 +136,7 @@ static PyObject *authGSSClientStep(PyObject *self, PyObject *args)
{
gss_client_state *state;
PyObject *pystate;
char *challenge;
char *challenge = NULL;
int result = 0;
if (!PyArg_ParseTuple(args, "Os", &pystate, &challenge))
......@@ -156,6 +158,26 @@ static PyObject *authGSSClientStep(PyObject *self, PyObject *args)
return Py_BuildValue("i", result);
}
static PyObject *authGSSClientResponseConf(PyObject *self, PyObject *args)
{
gss_client_state *state;
PyObject *pystate;
if (!PyArg_ParseTuple(args, "O", &pystate))
return NULL;
if (!PyCObject_Check(pystate)) {
PyErr_SetString(PyExc_TypeError, "Expected a context object");
return NULL;
}
state = (gss_client_state *)PyCObject_AsVoidPtr(pystate);
if (state == NULL)
return NULL;
return Py_BuildValue("i", state->responseConf);
}
static PyObject *authGSSClientResponse(PyObject *self, PyObject *args)
{
gss_client_state *state;
......@@ -200,7 +222,7 @@ static PyObject *authGSSClientUnwrap(PyObject *self, PyObject *args)
{
gss_client_state *state;
PyObject *pystate;
char *challenge;
char *challenge = NULL;
int result = 0;
if (!PyArg_ParseTuple(args, "Os", &pystate, &challenge))
......@@ -226,10 +248,12 @@ static PyObject *authGSSClientWrap(PyObject *self, PyObject *args)
{
gss_client_state *state;
PyObject *pystate;
char *challenge, *user = NULL;
char *challenge = NULL;
char *user = NULL;
int protect = 0;
int result = 0;
if (!PyArg_ParseTuple(args, "Os|z", &pystate, &challenge, &user))
if (!PyArg_ParseTuple(args, "Os|zi", &pystate, &challenge, &user, &protect))
return NULL;
if (!PyCObject_Check(pystate)) {
......@@ -241,7 +265,7 @@ static PyObject *authGSSClientWrap(PyObject *self, PyObject *args)
if (state == NULL)
return NULL;
result = authenticate_gss_client_wrap(state, challenge, user);
result = authenticate_gss_client_wrap(state, challenge, user, protect);
if (result == AUTH_GSS_ERROR)
return NULL;
......@@ -250,7 +274,7 @@ static PyObject *authGSSClientWrap(PyObject *self, PyObject *args)
static PyObject *authGSSServerInit(PyObject *self, PyObject *args)
{
const char *service;
const char *service = NULL;
gss_server_state *state;
PyObject *pystate;
int result = 0;
......@@ -298,7 +322,7 @@ static PyObject *authGSSServerStep(PyObject *self, PyObject *args)
{
gss_server_state *state;
PyObject *pystate;
char *challenge;
char *challenge = NULL;
int result = 0;
if (!PyArg_ParseTuple(args, "Os", &pystate, &challenge))
......@@ -395,6 +419,8 @@ static PyMethodDef KerberosMethods[] = {
"Do a client-side GSSAPI step."},
{"authGSSClientResponse", authGSSClientResponse, METH_VARARGS,
"Get the response from the last client-side GSSAPI step."},
{"authGSSClientResponseConf", authGSSClientResponseConf, METH_VARARGS,
"return 1 if confidentiality was set in the last unwrapped buffer, 0 otherwise."},
{"authGSSClientUserName", authGSSClientUserName, METH_VARARGS,
"Get the user name from the last client-side GSSAPI step."},
{"authGSSServerInit", authGSSServerInit, METH_VARARGS,
......
/**
* Copyright (c) 2006-2008 Apple Inc. All rights reserved.
* Copyright (c) 2006-2013 Apple Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......
/**
* Copyright (c) 2006-2008 Apple Inc. All rights reserved.
* Copyright (c) 2006-2013 Apple Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......
/**
* Copyright (c) 2006-2010 Apple Inc. All rights reserved.
* Copyright (c) 2006-2013 Apple Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -32,7 +32,7 @@ extern PyObject *KrbException_class;
char* server_principal_details(const char* service, const char* hostname)
{
char match[1024];
int match_len = 0;
size_t match_len = 0;
char* result = NULL;
int code;
......@@ -106,16 +106,18 @@ end:
return result;
}
int authenticate_gss_client_init(const char* service, long int gss_flags, gss_client_state* state)
int authenticate_gss_client_init(const char* service, const char* principal, long int gss_flags, gss_client_state* state)
{
OM_uint32 maj_stat;
OM_uint32 min_stat;
gss_buffer_desc name_token = GSS_C_EMPTY_BUFFER;
gss_buffer_desc principal_token = GSS_C_EMPTY_BUFFER;
int ret = AUTH_GSS_COMPLETE;
state->server_name = GSS_C_NO_NAME;
state->context = GSS_C_NO_CONTEXT;
state->gss_flags = gss_flags;
state->client_creds = GSS_C_NO_CREDENTIAL;
state->username = NULL;
state->response = NULL;
......@@ -132,6 +134,40 @@ int authenticate_gss_client_init(const char* service, long int gss_flags, gss_cl
goto end;
}
// Get credential for principal
if (principal && *principal)
{
gss_name_t name;
principal_token.length = strlen(principal);
principal_token.value = (char *)principal;
maj_stat = gss_import_name(&min_stat, &principal_token, GSS_C_NT_USER_NAME, &name);
if (GSS_ERROR(maj_stat))
{
set_gss_error(maj_stat, min_stat);
ret = AUTH_GSS_ERROR;
goto end;
}
maj_stat = gss_acquire_cred(&min_stat, name, GSS_C_INDEFINITE, GSS_C_NO_OID_SET, GSS_C_INITIATE,
&state->client_creds, NULL, NULL);
if (GSS_ERROR(maj_stat))
{
set_gss_error(maj_stat, min_stat);
ret = AUTH_GSS_ERROR;
goto end;
}
maj_stat = gss_release_name(&min_stat, &name);
if (GSS_ERROR(maj_stat))
{
set_gss_error(maj_stat, min_stat);
ret = AUTH_GSS_ERROR;
goto end;
}
}
end:
return ret;
}
......@@ -146,6 +182,8 @@ int authenticate_gss_client_clean(gss_client_state *state)
maj_stat = gss_delete_sec_context(&min_stat, &state->context, GSS_C_NO_BUFFER);
if (state->server_name != GSS_C_NO_NAME)
maj_stat = gss_release_name(&min_stat, &state->server_name);
if (state->client_creds != GSS_C_NO_CREDENTIAL)
maj_stat = gss_release_cred(&min_stat, &state->client_creds);
if (state->username != NULL)
{
free(state->username);
......@@ -178,14 +216,15 @@ int authenticate_gss_client_step(gss_client_state* state, const char* challenge)
// If there is a challenge (data from the server) we need to give it to GSS
if (challenge && *challenge)
{
int len;
size_t len;
input_token.value = base64_decode(challenge, &len);
input_token.length = len;
}
// Do GSSAPI step
Py_BEGIN_ALLOW_THREADS
maj_stat = gss_init_sec_context(&min_stat,
GSS_C_NO_CREDENTIAL,
state->client_creds,
&state->context,
state->server_name,
GSS_C_NO_OID,
......@@ -197,6 +236,7 @@ int authenticate_gss_client_step(gss_client_state* state, const char* challenge)
&output_token,
NULL,
NULL);
Py_END_ALLOW_THREADS
if ((maj_stat != GSS_S_COMPLETE) && (maj_stat != GSS_S_CONTINUE_NEEDED))
{
......@@ -262,18 +302,20 @@ int authenticate_gss_client_unwrap(gss_client_state *state, const char *challeng
gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
int ret = AUTH_GSS_CONTINUE;
int conf = 0;
// Always clear out the old response
if (state->response != NULL)
{
free(state->response);
state->response = NULL;
state->responseConf = 0;
}
// If there is a challenge (data from the server) we need to give it to GSS
if (challenge && *challenge)
{
int len;
size_t len;
input_token.value = base64_decode(challenge, &len);
input_token.length = len;
}
......@@ -283,7 +325,7 @@ int authenticate_gss_client_unwrap(gss_client_state *state, const char *challeng
state->context,
&input_token,
&output_token,
NULL,
&conf,
NULL);
if (maj_stat != GSS_S_COMPLETE)
......@@ -299,6 +341,7 @@ int authenticate_gss_client_unwrap(gss_client_state *state, const char *challeng
if (output_token.length)
{
state->response = base64_encode((const unsigned char *)output_token.value, output_token.length);
state->responseConf = conf;
maj_stat = gss_release_buffer(&min_stat, &output_token);
}
end:
......@@ -309,7 +352,7 @@ end:
return ret;
}
int authenticate_gss_client_wrap(gss_client_state* state, const char* challenge, const char* user)
int authenticate_gss_client_wrap(gss_client_state* state, const char* challenge, const char* user, int protect)
{
OM_uint32 maj_stat;
OM_uint32 min_stat;
......@@ -328,7 +371,7 @@ int authenticate_gss_client_wrap(gss_client_state* state, const char* challenge,
if (challenge && *challenge)
{
int len;
size_t len;
input_token.value = base64_decode(challenge, &len);
input_token.length = len;
}
......@@ -360,7 +403,7 @@ int authenticate_gss_client_wrap(gss_client_state* state, const char* challenge,
// Do GSSAPI wrap
maj_stat = gss_wrap(&min_stat,
state->context,
0,
protect,
GSS_C_QOP_DEFAULT,
&input_token,
NULL,
......@@ -488,7 +531,7 @@ int authenticate_gss_server_step(gss_server_state *state, const char *challenge)
// If there is a challenge (data from the server) we need to give it to GSS
if (challenge && *challenge)
{
int len;
size_t len;
input_token.value = base64_decode(challenge, &len);
input_token.length = len;
}
......@@ -499,6 +542,7 @@ int authenticate_gss_server_step(gss_server_state *state, const char *challenge)
goto end;
}
Py_BEGIN_ALLOW_THREADS
maj_stat = gss_accept_sec_context(&min_stat,
&state->context,
state->server_creds,
......@@ -510,6 +554,7 @@ int authenticate_gss_server_step(gss_server_state *state, const char *challenge)
NULL,
NULL,
&state->client_creds);
Py_END_ALLOW_THREADS
if (GSS_ERROR(maj_stat))
{
......
/**
* Copyright (c) 2006-2009 Apple Inc. All rights reserved.
* Copyright (c) 2006-2013 Apple Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -32,8 +32,10 @@ typedef struct {
gss_ctx_id_t context;
gss_name_t server_name;
long int gss_flags;
gss_cred_id_t client_creds;
char* username;
char* response;
int responseConf;
} gss_client_state;
typedef struct {
......@@ -49,11 +51,11 @@ typedef struct {
char* server_principal_details(const char* service, const char* hostname);
int authenticate_gss_client_init(const char* service, long int gss_flags, gss_client_state* state);
int authenticate_gss_client_init(const char* service, const char* principal, long int gss_flags, gss_client_state* state);
int authenticate_gss_client_clean(gss_client_state *state);
int authenticate_gss_client_step(gss_client_state *state, const char *challenge);
int authenticate_gss_client_unwrap(gss_client_state* state, const char* challenge);
int authenticate_gss_client_wrap(gss_client_state* state, const char* challenge, const char* user);
int authenticate_gss_client_wrap(gss_client_state* state, const char* challenge, const char* user, int protect);
int authenticate_gss_server_init(const char* service, gss_server_state* state);
int authenticate_gss_server_clean(gss_server_state *state);
......
/**
* Copyright (c) 2006-2009 Apple Inc. All rights reserved.
* Copyright (c) 2006-2013 Apple Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......
#!/usr/bin/env python
##
# Copyright (c) 2006-2009 Apple Inc. All rights reserved.
# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
......@@ -22,6 +23,21 @@ import httplib
import socket
import ssl
"""
Examples:
sudo ./test.py -s HTTP@example.com service
sudo ./test.py -u user01 -p user01 -s HTTP@example.com -r EXAMPLE.COM basic
sudo ./test.py -s HTTP@example.com -r EXAMPLE.COM gssapi
./test.py -s HTTP@example.com -h calendar.example.com -p 8008 server
For the gssapi and server tests you will need to kinit a principal on the server first.
"""
def main():
# Extract arguments
......@@ -115,7 +131,7 @@ def testGSSAPI(service):
if rc != 1:
return
rs, vs = kerberos.authGSSServerInit("");
rs, vs = kerberos.authGSSServerInit(service);
print "Status for authGSSServerInit = %s" % statusText(rs);
if rs != 1:
return
......@@ -197,7 +213,7 @@ def testHTTP(host, port, use_ssl, service):
return
try:
rc, vc = kerberos.authGSSClientInit(service);
rc, vc = kerberos.authGSSClientInit(service=service);
except kerberos.GSSError, e:
print "Could not initialize GSSAPI: %s/%s" % (e[0][0], e[1][0])
return
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment