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

New upstream version 1.1.14

parent c129f6a2
Metadata-Version: 1.1
Name: pykerberos
Version: 1.1.5
Version: 1.1.14
Summary: High-level interface to Kerberos
Home-page: UNKNOWN
Author: UNKNOWN
......
#!/usr/bin/env python
##
# Copyright (c) 2008 Jelmer Vernooij <jelmer@samba.org>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""A sample script showing how to verify a user with username and password."""
import argparse
import getpass
import kerberos
import sys
def main():
# construct arg parser
parser = argparse.ArgumentParser(description='Verify Kerberos login.')
parser.add_argument('--service', default='', help='the service to authenticate as')
parser.add_argument('--default_realm', default='', help='the realm to use if none is provided in the username')
parser.add_argument('--verify', default=False, action='store_true', help='enable KDC verification support')
parser.add_argument('user', metavar='user', help='the username to verify')
args = parser.parse_args()
print args.service
# get the password
password = getpass.getpass('Password: ')
# verify
try:
kerberos.checkPassword(args.user, password, args.service, args.default_realm, args.verify)
print "Successfully verified"
except kerberos.BasicAuthError as e:
print "{0} ({1})".format(*e.args)
if __name__ == "__main__":
main()
Metadata-Version: 1.1
Name: pykerberos
Version: 1.1.5
Version: 1.1.14
Summary: High-level interface to Kerberos
Home-page: UNKNOWN
Author: UNKNOWN
......
......@@ -3,6 +3,7 @@ MANIFEST.in
README.txt
setup.py
bin/ftp-gss
bin/login
pykerberos.egg-info/PKG-INFO
pykerberos.egg-info/SOURCES.txt
pykerberos.egg-info/dependency_links.txt
......
......@@ -27,17 +27,17 @@ class BasicAuthError(KrbError):
class GSSError(KrbError):
pass
def checkPassword(user, pswd, service, default_realm):
def checkPassword(user, pswd, service, default_realm, verify=True):
"""
This function provides a simple way to verify that a user name and password match
those normally used for Kerberos authentication. It does this by checking that the
supplied user name and password can be used to get a ticket for the supplied service.
If the user name does not contain a realm, then the default realm supplied is used.
NB For this to work properly the Kerberos must be configured properly on this machine.
That will likely mean ensuring that the edu.mit.Kerberos preference file has the correct
realms and KDCs listed.
@param user: a string containing the Kerberos user name. A realm may be
included by appending an '@' followed by the realm string to the actual user id.
If no realm is supplied, then the realm set in the default_realm argument will
......@@ -49,6 +49,8 @@ def checkPassword(user, pswd, service, default_realm):
@param default_realm: a string containing the default realm to use if one is not
supplied in the user argument. Note that Kerberos realms are normally all
uppercase (e.g., 'EXAMPLE.COM').
@param verify: a boolean flagging KDC verification as enabled or disabled
(default: True, i.e. enabled).
@return: True if authentication succeeds, False otherwise.
"""
......@@ -69,7 +71,7 @@ def getServerPrincipalDetails(service, hostname):
"""
This function returns the service principal for the server given a service type
and hostname. Details are looked up via the /etc/keytab file.
@param service: a string containing the Kerberos service type for the server.
@param hostname: a string containing the hostname of the server.
@return: a string containing the service principal.
......@@ -77,7 +79,7 @@ def getServerPrincipalDetails(service, hostname):
"""
GSSAPI Function Result Codes:
-1 : Error
0 : GSSAPI step continuation (only returned by 'Step' function)
1 : GSSAPI step complete, or function return OK
......@@ -85,21 +87,21 @@ GSSAPI Function Result Codes:
"""
# Some useful result codes
AUTH_GSS_CONTINUE = 0
AUTH_GSS_COMPLETE = 1
# Some useful gss flags
GSS_C_DELEG_FLAG = 1
GSS_C_MUTUAL_FLAG = 2
GSS_C_REPLAY_FLAG = 4
GSS_C_SEQUENCE_FLAG = 8
GSS_C_CONF_FLAG = 16
GSS_C_INTEG_FLAG = 32
GSS_C_ANON_FLAG = 64
GSS_C_PROT_READY_FLAG = 128
GSS_C_TRANS_FLAG = 256
def authGSSClientInit(service, principal=None, gssflags=GSS_C_MUTUAL_FLAG|GSS_C_SEQUENCE_FLAG):
AUTH_GSS_CONTINUE = 0
AUTH_GSS_COMPLETE = 1
# Some useful gss flags
GSS_C_DELEG_FLAG = 1
GSS_C_MUTUAL_FLAG = 2
GSS_C_REPLAY_FLAG = 4
GSS_C_SEQUENCE_FLAG = 8
GSS_C_CONF_FLAG = 16
GSS_C_INTEG_FLAG = 32
GSS_C_ANON_FLAG = 64
GSS_C_PROT_READY_FLAG = 128
GSS_C_TRANS_FLAG = 256
def authGSSClientInit(service, principal=None, gssflags=GSS_C_MUTUAL_FLAG|GSS_C_SEQUENCE_FLAG, mech_oid=None):
"""
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
......@@ -110,16 +112,19 @@ def authGSSClientInit(service, principal=None, gssflags=GSS_C_MUTUAL_FLAG|GSS_C_
@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
(e.g. GSS_C_DELEG_FLAG|GSS_C_MUTUAL_FLAG|GSS_C_SEQUENCE_FLAG will allow
for forwarding credentials to the remote host)
@param mech_oid: Optional GSS mech OID. Defaults to None (GSS_C_NO_OID).
Other possible values are GSS_MECH_OID_KRB5, GSS_MECH_OID_SPNEGO.
@return: a tuple of (result, context) where result is the result code (see above) and
context is an opaque value that will need to be passed to subsequent functions.
"""
def authGSSClientClean(context):
"""
Destroys the context for GSSAPI client-side authentication. After this call the context
object is invalid and should not be used again.
Destroys the context for GSSAPI client-side authentication. This function is provided for API
compatibility with original pykerberos but does nothing. The context object destroys itself
when it is reclaimed.
@param context: the context object returned from authGSSClientInit.
@return: a result code (see above).
......@@ -160,22 +165,22 @@ def authGSSClientUserName(context):
@return: a string containing the user name.
"""
def authGSSClientUnwrap(context, challenge):
"""
Perform the client side GSSAPI unwrap step
@param challenge: a string containing the base64-encoded server data.
@return: a result code (see above)
"""
def authGSSClientUnwrap(context, challenge):
"""
Perform the client side GSSAPI unwrap step
def authGSSClientWrap(context, data, user=None):
"""
Perform the client side GSSAPI wrap step.
@param data:the result of the authGSSClientResponse after the authGSSClientUnwrap
@param user: the user to authorize
@return: a result code (see above)
"""
@param challenge: a string containing the base64-encoded server data.
@return: a result code (see above)
"""
def authGSSClientWrap(context, data, user=None):
"""
Perform the client side GSSAPI wrap step.
@param data:the result of the authGSSClientResponse after the authGSSClientUnwrap
@param user: the user to authorize
@return: a result code (see above)
"""
def authGSSServerInit(service):
"""
......@@ -191,8 +196,9 @@ def authGSSServerInit(service):
def authGSSServerClean(context):
"""
Destroys the context for GSSAPI server-side authentication. After this call the context
object is invalid and should not be used again.
Destroys the context for GSSAPI server-side authentication. This function is provided for API
compatibility with original pykerberos but does nothing. The context object destroys itself
when it is reclaimed.
@param context: the context object returned from authGSSServerInit.
@return: a result code (see above).
......@@ -232,4 +238,3 @@ def authGSSServerTargetName(context):
@param context: the context object returned from authGSSServerInit.
@return: a string containing the target name.
"""
......@@ -26,33 +26,39 @@ Kerberos authentication based on <http://www.ietf.org/rfc/rfc4559.txt>.
"""
# Backport from Python 2.7 in case we're in 2.6.
def check_output(*popenargs, **kwargs):
process = subprocess.Popen(stdout=subprocess.PIPE, *popenargs, **kwargs)
output, unused_err = process.communicate()
retcode = process.poll()
if retcode:
cmd = kwargs.get("args")
if cmd is None:
cmd = popenargs[0]
raise subprocess.CalledProcessError(retcode, cmd, output=output)
return output
def check_krb5_config(*options, **kwargs):
try:
cmd = kwargs.get('command_name', 'krb5-config')
process = subprocess.Popen((cmd,) + options, stdout=subprocess.PIPE, universal_newlines=True)
output, unused_err = process.communicate()
retcode = process.poll()
if retcode:
raise subprocess.CalledProcessError(retcode, cmd, output=output)
return output.split()
except OSError as e:
if e.errno == 2 and cmd != "krb5-config.mit":
try:
return check_krb5_config(*options, command_name="krb5-config.mit")
except OSError as e2:
if e2.errno == 2:
raise Exception("You are missing krb5-config(.mit)")
def check_krb5_version():
krb5_vers = check_krb5_config("--version")
if krb5_vers and len(krb5_vers) == 4:
if int(krb5_vers[3].split('.')[1].split('-')[0]) >= 10:
return r'-DGSSAPI_EXT'
extra_link_args = check_output(
["krb5-config", "--libs", "gssapi"],
universal_newlines=True
).split()
extra_compile_args = check_output(
["krb5-config", "--cflags", "gssapi"],
universal_newlines=True
).split()
extra_link_args = check_krb5_config("--libs", "gssapi")
extra_compile_args = check_krb5_config("--cflags", "gssapi")
krb5_ver = check_krb5_version()
if krb5_ver:
extra_compile_args.append(krb5_ver)
setup (
name = "pykerberos",
version = "1.1.5",
version = "1.1.14",
description = "High-level interface to Kerberos",
long_description=long_description,
license="ASL 2.0",
......
......@@ -55,8 +55,8 @@ char *base64_encode(const unsigned char *value, size_t vlen)
}
if (vlen > 0)
{
*out++ = basis_64[value[0] >> 2];
unsigned char oval = (value[0] << 4) & 0x30;
*out++ = basis_64[value[0] >> 2];
if (vlen > 1) oval |= value[1] >> 4;
*out++ = basis_64[oval];
*out++ = (vlen < 2) ? '=' : basis_64[(value[1] << 2) & 0x3C];
......@@ -74,12 +74,11 @@ char *base64_encode(const unsigned char *value, size_t vlen)
// (result) : new unsigned char[] - decoded result
unsigned char *base64_decode(const char *value, size_t *rlen)
{
*rlen = 0;
int c1, c2, c3, c4;
size_t vlen = strlen(value);
unsigned char *result =(unsigned char *)malloc((vlen * 3) / 4 + 1);
unsigned char *out = result;
*rlen = 0;
while (1)
{
......
This diff is collapsed.
......@@ -26,9 +26,9 @@
extern PyObject *BasicAuthException_class;
static void set_basicauth_error(krb5_context context, krb5_error_code code);
static krb5_error_code verify_krb5_user(krb5_context context, krb5_principal principal, const char *password, krb5_principal server);
static krb5_error_code verify_krb5_user(krb5_context context, krb5_principal principal, const char *password, krb5_principal server, unsigned char verify);
int authenticate_user_krb5pwd(const char *user, const char *pswd, const char *service, const char *default_realm)
int authenticate_user_krb5pwd(const char *user, const char *pswd, const char *service, const char *default_realm, unsigned char verify)
{
krb5_context kcontext = NULL;
krb5_error_code code;
......@@ -38,59 +38,56 @@ int authenticate_user_krb5pwd(const char *user, const char *pswd, const char *se
char *name = NULL;
char *p = NULL;
// create kerberos context
code = krb5_init_context(&kcontext);
if (code)
{
PyErr_SetObject(BasicAuthException_class, Py_BuildValue("((s:i))",
"Cannot initialize Kerberos5 context", code));
if (code) {
PyErr_SetObject(BasicAuthException_class, Py_BuildValue("((s:i))", "Cannot initialize Kerberos5 context", code));
return 0;
}
ret = krb5_parse_name (kcontext, service, &server);
if (ret)
{
// parse service name to get the server principal
ret = krb5_parse_name(kcontext, service, &server);
if (ret) {
set_basicauth_error(kcontext, ret);
ret = 0;
goto end;
}
// unparse server pinrcipal again to get cannonical string representation
code = krb5_unparse_name(kcontext, server, &name);
if (code)
{
if (code) {
set_basicauth_error(kcontext, code);
ret = 0;
goto end;
}
#ifdef PRINTFS
printf("Using %s as server principal for password verification\n", name);
#endif
// free cannonical server principal
free(name);
name = NULL;
// construct user principal string from username and default realm
name = (char *)malloc(256);
p = strchr(user, '@');
if (p == NULL)
{
if (p == NULL) {
snprintf(name, 256, "%s@%s", user, default_realm);
}
else
{
} else {
snprintf(name, 256, "%s", user);
}
// parse it into principal structure
code = krb5_parse_name(kcontext, name, &client);
if (code)
{
if (code) {
set_basicauth_error(kcontext, code);
ret = 0;
goto end;
}
code = verify_krb5_user(kcontext, client, pswd, server);
if (code)
{
code = verify_krb5_user(kcontext, client, pswd, server, verify);
if (code) {
ret = 0;
goto end;
}
......@@ -101,6 +98,7 @@ end:
#ifdef PRINTFS
printf("kerb_authenticate_user_krb5pwd ret=%d user=%s authtype=%s\n", ret, user, "Basic");
#endif
if (name)
free(name);
if (client)
......@@ -113,35 +111,61 @@ end:
}
/* Inspired by krb5_verify_user from Heimdal */
static krb5_error_code verify_krb5_user(krb5_context context, krb5_principal principal, const char *password, krb5_principal server)
static krb5_error_code verify_krb5_user(krb5_context context, krb5_principal principal, const char *password, krb5_principal server, unsigned char verify)
{
krb5_creds creds;
krb5_get_init_creds_opt gic_options;
krb5_get_init_creds_opt *gic_options;
krb5_verify_init_creds_opt vic_options;
krb5_error_code ret;
char *name = NULL;
memset(&creds, 0, sizeof(creds));
// verify passed in client principal
ret = krb5_unparse_name(context, principal, &name);
if (ret == 0)
{
if (ret == 0) {
#ifdef PRINTFS
printf("Trying to get TGT for user %s\n", name);
#endif
free(name);
}
krb5_get_init_creds_opt_init(&gic_options);
ret = krb5_get_init_creds_password(context, &creds, principal, (char *)password, NULL, NULL, 0, NULL, &gic_options);
if (ret)
{
// verify passed in server principal if needed
if (verify) {
ret = krb5_unparse_name(context, server, &name);
if (ret == 0) {
#ifdef PRINTFS
printf("Trying to get TGT for service %s\n", name);
#endif
free(name);
}
}
// verify password
krb5_get_init_creds_opt_alloc(context, &gic_options);
ret = krb5_get_init_creds_password(context, &creds, principal, (char *)password, NULL, NULL, 0, NULL, gic_options);
if (ret) {
set_basicauth_error(context, ret);
goto end;
}
// verify response authenticity
if (verify) {
krb5_verify_init_creds_opt_init(&vic_options);
krb5_verify_init_creds_opt_set_ap_req_nofail(&vic_options, 1);
ret = krb5_verify_init_creds(context, &creds, server, NULL, NULL, &vic_options);
if (ret) {
set_basicauth_error(context, ret);
}
}
end:
// clean up
krb5_free_cred_contents(context, &creds);
if (gic_options)
krb5_get_init_creds_opt_free(context, gic_options);
return ret;
}
......
......@@ -20,4 +20,4 @@
#define krb5_get_err_text(context,code) error_message(code)
int authenticate_user_krb5pwd(const char *user, const char *pswd, const char *service, const char *default_realm);
int authenticate_user_krb5pwd(const char *user, const char *pswd, const char *service, const char *default_realm, unsigned char verify);
This diff is collapsed.
......@@ -17,7 +17,9 @@
#include <gssapi/gssapi.h>
#include <gssapi/gssapi_generic.h>
#include <gssapi/gssapi_krb5.h>
#ifdef GSSAPI_EXT
#include <gssapi/gssapi_ext.h>
#endif
#define krb5_get_err_text(context,code) error_message(code)
#define AUTH_GSS_ERROR -1
......@@ -31,6 +33,7 @@
typedef struct {
gss_ctx_id_t context;
gss_name_t server_name;
gss_OID mech_oid;
long int gss_flags;
gss_cred_id_t client_creds;
char* username;
......@@ -51,12 +54,15 @@ typedef struct {
char* server_principal_details(const char* service, const char* hostname);
int authenticate_gss_client_init(const char* service, const char* principal, long int gss_flags, gss_client_state* state);
int authenticate_gss_client_init(const char* service, const char* principal, long int gss_flags, gss_OID mech_oid, 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 protect);
#ifdef GSSAPI_EXT
int authenticate_gss_client_wrap_iov(gss_client_state* state, const char* challenge, int protect, int *pad_len);
int authenticate_gss_client_unwrap_iov(gss_client_state* state, const char* challenge);
#endif
int authenticate_gss_server_init(const char* service, gss_server_state* state);
int authenticate_gss_server_clean(gss_server_state *state);
int authenticate_gss_server_step(gss_server_state *state, const char *challenge);
......@@ -41,7 +41,7 @@ static krb5_error_code verify_krb5_user(krb5_context context,
krb5_get_init_creds_opt gic_options;
krb5_error_code code;
int ret = 0;
#ifdef PRINTFS
{
char *name = NULL;
......@@ -57,7 +57,7 @@ static krb5_error_code verify_krb5_user(krb5_context context,
krb5_get_init_creds_opt_set_renew_life(&gic_options, 0);
memset(creds, 0, sizeof(krb5_creds));
code = krb5_get_init_creds_password(context, creds, principal,
(char *)password, NULL, NULL, 0,
(char *)service, &gic_options);
......@@ -92,7 +92,7 @@ int change_user_krb5pwd(const char *user, const char* oldpswd, const char *newps
name = (char *)malloc(256);
snprintf(name, 256, "%s", user);
code = krb5_parse_name(kcontext, name, &client);
if (code) {
set_pwchange_error(kcontext, code);
......@@ -111,14 +111,15 @@ int change_user_krb5pwd(const char *user, const char* oldpswd, const char *newps
}
if (result_code) {
char *message = NULL;
asprintf(&message, "%.*s: %.*s",
if (asprintf(&message, "%.*s: %.*s",
(int) result_code_string.length,
(char *) result_code_string.data,
(int) result_string.length,
(char *) result_string.data);
PyErr_SetObject(PwdChangeException_class, Py_BuildValue("((s:i))",
(char *) result_string.data) > -1) {
PyErr_SetObject(PwdChangeException_class, Py_BuildValue("((s:i))",
message, result_code));
free(message);
free(message);
}
goto end;
}
......@@ -134,4 +135,3 @@ end:
krb5_free_context(kcontext);
return ret;
}
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