pykerberos-1.1.5/0000755000076500000240000000000012314246022014302 5ustar stefanstaff00000000000000pykerberos-1.1.5/bin/0000755000076500000240000000000012314246022015052 5ustar stefanstaff00000000000000pykerberos-1.1.5/bin/ftp-gss0000755000076500000240000001027212314245233016370 0ustar stefanstaff00000000000000#!/usr/bin/env python ## # Copyright (c) 2008 Jelmer Vernooij # # 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. """Support for secure authentication using GSSAPI over FTP. See RFC2228 for details. """ from ftplib import * import base64, ftplib, getpass, kerberos, socket, sys class SecureFtp(FTP): """Extended version of ftplib.FTP that can authenticate using GSSAPI.""" def mic_putcmd(self, line): rc = kerberos.authGSSClientWrap(self.vc, base64.b64encode(line)) wrapped = kerberos.authGSSClientResponse(self.vc) FTP.putcmd(self, "MIC " + wrapped) def mic_getline(self): resp = FTP.getline(self) assert resp[:4] == '631 ' rc = kerberos.authGSSClientUnwrap(self.vc, resp[4:].strip("\r\n")) response = base64.b64decode(kerberos.authGSSClientResponse(self.vc)) return response def gssapi_login(self, user): # Try GSSAPI login first resp = self.sendcmd('AUTH GSSAPI') if resp[:3] == '334': rc, self.vc = kerberos.authGSSClientInit("ftp@%s" % self.host) if kerberos.authGSSClientStep(self.vc, "") != 1: while resp[:3] in ('334', '335'): authdata = kerberos.authGSSClientResponse(self.vc) resp = self.sendcmd('ADAT ' + authdata) if resp[:9] in ('235 ADAT=', '335 ADAT='): rc = kerberos.authGSSClientStep(self.vc, resp[9:]) assert ((resp[:3] == '235' and rc == 1) or (resp[:3] == '335' and rc == 0)) print "Authenticated as %s" % kerberos.authGSSClientUserName(self.vc) # Monkey patch ftplib self.putcmd = self.mic_putcmd self.getline = self.mic_getline self.sendcmd('USER ' + user) return resp def test(): '''Test program. Usage: ftp [-d] [-u[user]] [-r[file]] host [-l[dir]] [-d[dir]] [-p] [file] ... -d dir -l list -u user ''' from getopt import getopt if len(sys.argv) < 2: print test.__doc__ sys.exit(0) (opts, args) = getopt(sys.argv[1:], "d:u:r:") debugging = 0 rcfile = None userid = None for (k, v) in opts: if k == "-d": debugging += 1 elif k == "-u": userid = v elif k == "-r": rcfile = v host = args[0] ftp = SecureFtp(host) ftp.set_debuglevel(debugging) passwd = acct = '' try: netrc = Netrc(rcfile) except IOError: if rcfile is not None and userid is None: sys.stderr.write("Could not open account file" " -- using anonymous login.") userid = '' else: if userid is None: try: userid, passwd, acct = netrc.get_account(host) except KeyError: # no account for host sys.stderr.write( "No account -- using anonymous login.") userid = '' try: if userid: ftp.gssapi_login(userid) else: ftp.login(userid, passwd, acct) except ftplib.error_perm, e: # Fall back to regular authentication ftp.login(userid, passwd, acct) for file in args[1:]: if file[:2] == '-l': ftp.dir(file[2:]) elif file[:2] == '-d': cmd = 'CWD' if file[2:]: cmd = cmd + ' ' + file[2:] resp = ftp.sendcmd(cmd) elif file == '-p': ftp.set_pasv(not ftp.passiveserver) else: ftp.retrbinary('RETR ' + file, \ sys.stdout.write, 1024) ftp.quit() if __name__ == '__main__': test() pykerberos-1.1.5/LICENSE0000644000076500000240000002613612314245233015322 0ustar stefanstaff00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] 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. pykerberos-1.1.5/MANIFEST.in0000644000076500000240000000013412314245233016041 0ustar stefanstaff00000000000000recursive-include src *.h recursive-include pysrc * recursive-include bin * include LICENSE pykerberos-1.1.5/PKG-INFO0000644000076500000240000000157212314246022015404 0ustar stefanstaff00000000000000Metadata-Version: 1.1 Name: pykerberos Version: 1.1.5 Summary: High-level interface to Kerberos Home-page: UNKNOWN Author: UNKNOWN Author-email: UNKNOWN License: ASL 2.0 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 . Platform: UNKNOWN Classifier: License :: OSI Approved :: Apache Software License Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 3 Classifier: Topic :: Software Development :: Libraries :: Python Modules Classifier: Topic :: System :: Systems Administration :: Authentication/Directory pykerberos-1.1.5/pykerberos.egg-info/0000755000076500000240000000000012314246022020161 5ustar stefanstaff00000000000000pykerberos-1.1.5/pykerberos.egg-info/dependency_links.txt0000644000076500000240000000000112314246022024227 0ustar stefanstaff00000000000000 pykerberos-1.1.5/pykerberos.egg-info/PKG-INFO0000644000076500000240000000157212314246022021263 0ustar stefanstaff00000000000000Metadata-Version: 1.1 Name: pykerberos Version: 1.1.5 Summary: High-level interface to Kerberos Home-page: UNKNOWN Author: UNKNOWN Author-email: UNKNOWN License: ASL 2.0 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 . Platform: UNKNOWN Classifier: License :: OSI Approved :: Apache Software License Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 3 Classifier: Topic :: Software Development :: Libraries :: Python Modules Classifier: Topic :: System :: Systems Administration :: Authentication/Directory pykerberos-1.1.5/pykerberos.egg-info/SOURCES.txt0000644000076500000240000000054412314246022022050 0ustar stefanstaff00000000000000LICENSE MANIFEST.in README.txt setup.py bin/ftp-gss pykerberos.egg-info/PKG-INFO pykerberos.egg-info/SOURCES.txt pykerberos.egg-info/dependency_links.txt pykerberos.egg-info/top_level.txt pysrc/kerberos.py src/base64.c src/base64.h src/kerberos.c src/kerberosbasic.c src/kerberosbasic.h src/kerberosgss.c src/kerberosgss.h src/kerberospw.c src/kerberospw.hpykerberos-1.1.5/pykerberos.egg-info/top_level.txt0000644000076500000240000000001112314246022022703 0ustar stefanstaff00000000000000kerberos pykerberos-1.1.5/pysrc/0000755000076500000240000000000012314246022015442 5ustar stefanstaff00000000000000pykerberos-1.1.5/pysrc/kerberos.py0000644000076500000240000002224012314245233017633 0ustar stefanstaff00000000000000## # 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. # 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. ## """ PyKerberos Function Description. """ class KrbError(Exception): pass class BasicAuthError(KrbError): pass class GSSError(KrbError): pass def checkPassword(user, pswd, service, default_realm): """ 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 be used. @param pswd: a string containing the password for the user. @param service: a string containging the Kerberos service to check access for. This will be of the form 'sss/xx.yy.zz', where 'sss' is the service identifier (e.g., 'http', 'krbtgt'), and 'xx.yy.zz' is the hostname of the server. @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'). @return: True if authentication succeeds, False otherwise. """ def changePassword(user, oldpswd, newpswd): """ This function allows to change the user password on the KDC. @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 be used. @param oldpswd: a string containing the old (current) password for the user. @param newpswd: a string containging the new password for the user. @return: True if password changing succeeds, False otherwise. """ 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. """ """ GSSAPI Function Result Codes: -1 : Error 0 : GSSAPI step continuation (only returned by 'Step' function) 1 : GSSAPI step complete, or function return OK """ # 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): """ 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 the context once all GSSAPI operations are complete. @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) @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. @param context: the context object returned from authGSSClientInit. @return: a result code (see above). """ def authGSSClientStep(context, challenge): """ Processes a single GSSAPI client-side step using the supplied server data. @param context: the context object returned from authGSSClientInit. @param challenge: a string containing the base64-encoded server data (which may be empty for the first step). @return: a result code (see above). """ def authGSSClientResponse(context): """ Get the client response from the last successful GSSAPI client-side step. @param context: the context object returned from authGSSClientInit. @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. This method must only be called after authGSSClientStep returns a complete response code. @param context: the context object returned from authGSSClientInit. @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 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): """ Initializes a context for GSSAPI server-side authentication with the given service principal. authGSSServerClean must be called after this function returns an OK result to dispose of the context once all GSSAPI operations are complete. @param service: a string containing the service principal in the form 'type@fqdn' (e.g. 'imap@mail.apple.com'). @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 authGSSServerClean(context): """ Destroys the context for GSSAPI server-side authentication. After this call the context object is invalid and should not be used again. @param context: the context object returned from authGSSServerInit. @return: a result code (see above). """ def authGSSServerStep(context, challenge): """ Processes a single GSSAPI server-side step using the supplied client data. @param context: the context object returned from authGSSServerInit. @param challenge: a string containing the base64-encoded client data. @return: a result code (see above). """ def authGSSServerResponse(context): """ Get the server response from the last successful GSSAPI server-side step. @param context: the context object returned from authGSSServerInit. @return: a string containing the base64-encoded server data to be sent to the client. """ def authGSSServerUserName(context): """ Get the user name of the principal trying to authenticate to the server. This method must only be called after authGSSServerStep returns a complete or continue response code. @param context: the context object returned from authGSSServerInit. @return: a string containing the user name. """ def authGSSServerTargetName(context): """ Get the target name if the server did not supply its own credentials. This method must only be called after authGSSServerStep returns a complete or continue response code. @param context: the context object returned from authGSSServerInit. @return: a string containing the target name. """ pykerberos-1.1.5/README.txt0000644000076500000240000000473512314245233016014 0ustar stefanstaff00000000000000========================================================= PyKerberos Package 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. 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. ========================================================= 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 . Much of the C-code here is adapted from Apache's mod_auth_kerb-5.0rc7. ======== CONTENTS ======== src/ : directory in which C source code resides. setup.py : Python distutils extension build script. config/ : directory of useful Kerberos config files. edu.mit.Kerberos : example Kerberos .ini file. README.txt : this file! kerberos.py : Python api documentation/stub implementation. ===== BUILD ===== In this directory, run: python setup.py build ======= TESTING ======= You must have a valid Kerberos setup on the test machine and you should ensure that you have valid Kerberos tickets for any client authentication being done (run 'klist' on the command line). Additionally, for the server: it must have been configured as a valid Kerberos service with the Kerbersos server for its realm - this usually requires running kadmin on the server machine to add the principal and generate a keytab entry for it (run 'sudo klist -k' to see the currently available keytab entries). Make sure that PYTHONPATH includes the appropriate build/lib.xxxx directory. Then run test.py with suitable command line arguments: python test.py -u userid -p password -s service -u : user id for basic authenticate -p : password for basic authenticate -s : service principal for GSSAPI authentication (defaults to 'http@host.example.com') =========== Python APIs =========== See kerberos.py. pykerberos-1.1.5/setup.cfg0000644000076500000240000000007312314246022016123 0ustar stefanstaff00000000000000[egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 pykerberos-1.1.5/setup.py0000644000076500000240000000506112314245512016021 0ustar stefanstaff00000000000000## # Copyright (c) 2006-2008 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. # 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. ## from setuptools import setup, Extension import subprocess import sys 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 . """ # 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 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() setup ( name = "pykerberos", version = "1.1.5", description = "High-level interface to Kerberos", long_description=long_description, license="ASL 2.0", classifiers = [ "License :: OSI Approved :: Apache Software License", "Programming Language :: Python :: 2", "Programming Language :: Python :: 3", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: System :: Systems Administration :: Authentication/Directory" ], ext_modules = [ Extension( "kerberos", extra_link_args = extra_link_args, extra_compile_args = extra_compile_args, sources = [ "src/kerberos.c", "src/kerberosbasic.c", "src/kerberosgss.c", "src/kerberospw.c", "src/base64.c" ], ), ], ) pykerberos-1.1.5/src/0000755000076500000240000000000012314246022015071 5ustar stefanstaff00000000000000pykerberos-1.1.5/src/base64.c0000644000076500000240000000714512314245233016333 0ustar stefanstaff00000000000000/** * 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. * 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. **/ #include "base64.h" #include #include // base64 tables static char basis_64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static signed char index_64[128] = { -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63, 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1, -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1 }; #define CHAR64(c) (((c) < 0 || (c) > 127) ? -1 : index_64[(c)]) // base64_encode : base64 encode // // value : data to encode // vlen : length of data // (result) : new char[] - c-str of result char *base64_encode(const unsigned char *value, size_t vlen) { char *result = (char *)malloc((vlen * 4) / 3 + 5); char *out = result; while (vlen >= 3) { *out++ = basis_64[value[0] >> 2]; *out++ = basis_64[((value[0] << 4) & 0x30) | (value[1] >> 4)]; *out++ = basis_64[((value[1] << 2) & 0x3C) | (value[2] >> 6)]; *out++ = basis_64[value[2] & 0x3F]; value += 3; vlen -= 3; } if (vlen > 0) { *out++ = basis_64[value[0] >> 2]; unsigned char oval = (value[0] << 4) & 0x30; if (vlen > 1) oval |= value[1] >> 4; *out++ = basis_64[oval]; *out++ = (vlen < 2) ? '=' : basis_64[(value[1] << 2) & 0x3C]; *out++ = '='; } *out = '\0'; return result; } // base64_decode : base64 decode // // value : c-str to decode // rlen : length of decoded result // (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; while (1) { if (value[0]==0) return result; c1 = value[0]; if (CHAR64(c1) == -1) goto base64_decode_error;; c2 = value[1]; if (CHAR64(c2) == -1) goto base64_decode_error;; c3 = value[2]; if ((c3 != '=') && (CHAR64(c3) == -1)) goto base64_decode_error;; c4 = value[3]; if ((c4 != '=') && (CHAR64(c4) == -1)) goto base64_decode_error;; value += 4; *out++ = (CHAR64(c1) << 2) | (CHAR64(c2) >> 4); *rlen += 1; if (c3 != '=') { *out++ = ((CHAR64(c2) << 4) & 0xf0) | (CHAR64(c3) >> 2); *rlen += 1; if (c4 != '=') { *out++ = ((CHAR64(c3) << 6) & 0xc0) | CHAR64(c4); *rlen += 1; } } } base64_decode_error: *result = 0; *rlen = 0; return result; } pykerberos-1.1.5/src/base64.h0000644000076500000240000000140412314245233016330 0ustar stefanstaff00000000000000/** * 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. * 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. **/ #include char *base64_encode(const unsigned char *value, size_t vlen); unsigned char *base64_decode(const char *value, size_t *rlen); pykerberos-1.1.5/src/kerberos.c0000644000076500000240000004254612314245233017067 0ustar stefanstaff00000000000000/** * 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. * 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. **/ #include #include "kerberosbasic.h" #include "kerberospw.h" #include "kerberosgss.h" #if PY_MAJOR_VERSION >= 3 #define PyInt_FromLong PyLong_FromLong #endif PyObject *KrbException_class; PyObject *BasicAuthException_class; PyObject *PwdChangeException_class; PyObject *GssException_class; static PyObject *checkPassword(PyObject *self, PyObject *args) { 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)) return NULL; result = authenticate_user_krb5pwd(user, pswd, service, default_realm); if (result) return Py_INCREF(Py_True), Py_True; else return NULL; } static PyObject *changePassword(PyObject *self, PyObject *args) { const char *newpswd = NULL; const char *oldpswd = NULL; const char *user = NULL; int result = 0; if (!PyArg_ParseTuple(args, "sss", &user, &oldpswd, &newpswd)) return NULL; result = change_user_krb5pwd(user, oldpswd, newpswd); if (result) return Py_INCREF(Py_True), Py_True; else return NULL; } static PyObject *getServerPrincipalDetails(PyObject *self, PyObject *args) { const char *service = NULL; const char *hostname = NULL; char* result; if (!PyArg_ParseTuple(args, "ss", &service, &hostname)) return NULL; result = server_principal_details(service, hostname); if (result != NULL) { PyObject* pyresult = Py_BuildValue("s", result); free(result); return pyresult; } else return NULL; } static PyObject* authGSSClientInit(PyObject* self, PyObject* args, PyObject* keywds) { const char *service = NULL; const char *principal = NULL; gss_client_state *state; PyObject *pystate; 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|zl", kwlist, &service, &principal, &gss_flags)) return NULL; state = (gss_client_state *) malloc(sizeof(gss_client_state)); #if PY_MAJOR_VERSION >= 3 pystate = PyCapsule_New(state, NULL, NULL); #else pystate = PyCObject_FromVoidPtr(state, NULL); #endif result = authenticate_gss_client_init(service, principal, gss_flags, state); if (result == AUTH_GSS_ERROR) return NULL; return Py_BuildValue("(iO)", result, pystate); } static PyObject *authGSSClientClean(PyObject *self, PyObject *args) { gss_client_state *state; PyObject *pystate; int result = 0; if (!PyArg_ParseTuple(args, "O", &pystate)) return NULL; #if PY_MAJOR_VERSION >= 3 if (!PyCapsule_CheckExact(pystate)) { #else if (!PyCObject_Check(pystate)) { #endif PyErr_SetString(PyExc_TypeError, "Expected a context object"); return NULL; } #if PY_MAJOR_VERSION >= 3 state = PyCapsule_GetPointer(pystate, NULL); #else state = (gss_client_state *)PyCObject_AsVoidPtr(pystate); #endif if (state != NULL) { result = authenticate_gss_client_clean(state); free(state); #if PY_MAJOR_VERSION >= 3 PyCapsule_SetPointer(pystate, NULL); #else PyCObject_SetVoidPtr(pystate, NULL); #endif } return Py_BuildValue("i", result); } static PyObject *authGSSClientStep(PyObject *self, PyObject *args) { gss_client_state *state; PyObject *pystate; char *challenge = NULL; int result = 0; if (!PyArg_ParseTuple(args, "Os", &pystate, &challenge)) return NULL; #if PY_MAJOR_VERSION >= 3 if (!PyCapsule_CheckExact(pystate)) { #else if (!PyCObject_Check(pystate)) { #endif PyErr_SetString(PyExc_TypeError, "Expected a context object"); return NULL; } #if PY_MAJOR_VERSION >= 3 state = PyCapsule_GetPointer(pystate, NULL); #else state = (gss_client_state *)PyCObject_AsVoidPtr(pystate); #endif if (state == NULL) return NULL; result = authenticate_gss_client_step(state, challenge); if (result == AUTH_GSS_ERROR) return NULL; 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 PY_MAJOR_VERSION >= 3 if (!PyCapsule_CheckExact(pystate)) { #else if (!PyCObject_Check(pystate)) { #endif PyErr_SetString(PyExc_TypeError, "Expected a context object"); return NULL; } #if PY_MAJOR_VERSION >= 3 state = PyCapsule_GetPointer(pystate, NULL); #else state = (gss_client_state *)PyCObject_AsVoidPtr(pystate); #endif if (state == NULL) return NULL; return Py_BuildValue("i", state->responseConf); } static PyObject *authGSSClientResponse(PyObject *self, PyObject *args) { gss_client_state *state; PyObject *pystate; if (!PyArg_ParseTuple(args, "O", &pystate)) return NULL; #if PY_MAJOR_VERSION >= 3 if (!PyCapsule_CheckExact(pystate)) { #else if (!PyCObject_Check(pystate)) { #endif PyErr_SetString(PyExc_TypeError, "Expected a context object"); return NULL; } #if PY_MAJOR_VERSION >= 3 state = PyCapsule_GetPointer(pystate, NULL); #else state = (gss_client_state *)PyCObject_AsVoidPtr(pystate); #endif if (state == NULL) return NULL; return Py_BuildValue("s", state->response); } static PyObject *authGSSClientUserName(PyObject *self, PyObject *args) { gss_client_state *state; PyObject *pystate; if (!PyArg_ParseTuple(args, "O", &pystate)) return NULL; #if PY_MAJOR_VERSION >= 3 if (!PyCapsule_CheckExact(pystate)) { #else if (!PyCObject_Check(pystate)) { #endif PyErr_SetString(PyExc_TypeError, "Expected a context object"); return NULL; } #if PY_MAJOR_VERSION >= 3 state = PyCapsule_GetPointer(pystate, NULL); #else state = (gss_client_state *)PyCObject_AsVoidPtr(pystate); #endif if (state == NULL) return NULL; return Py_BuildValue("s", state->username); } static PyObject *authGSSClientUnwrap(PyObject *self, PyObject *args) { gss_client_state *state; PyObject *pystate; char *challenge = NULL; int result = 0; if (!PyArg_ParseTuple(args, "Os", &pystate, &challenge)) return NULL; #if PY_MAJOR_VERSION >= 3 if (!PyCapsule_CheckExact(pystate)) { #else if (!PyCObject_Check(pystate)) { #endif PyErr_SetString(PyExc_TypeError, "Expected a context object"); return NULL; } #if PY_MAJOR_VERSION >= 3 state = PyCapsule_GetPointer(pystate, NULL); #else state = (gss_client_state *)PyCObject_AsVoidPtr(pystate); #endif if (state == NULL) return NULL; result = authenticate_gss_client_unwrap(state, challenge); if (result == AUTH_GSS_ERROR) return NULL; return Py_BuildValue("i", result); } static PyObject *authGSSClientWrap(PyObject *self, PyObject *args) { gss_client_state *state; PyObject *pystate; char *challenge = NULL; char *user = NULL; int protect = 0; int result = 0; if (!PyArg_ParseTuple(args, "Os|zi", &pystate, &challenge, &user, &protect)) return NULL; #if PY_MAJOR_VERSION >= 3 if (!PyCapsule_CheckExact(pystate)) { #else if (!PyCObject_Check(pystate)) { #endif PyErr_SetString(PyExc_TypeError, "Expected a context object"); return NULL; } #if PY_MAJOR_VERSION >= 3 state = PyCapsule_GetPointer(pystate, NULL); #else state = (gss_client_state *)PyCObject_AsVoidPtr(pystate); #endif if (state == NULL) return NULL; result = authenticate_gss_client_wrap(state, challenge, user, protect); if (result == AUTH_GSS_ERROR) return NULL; return Py_BuildValue("i", result); } static PyObject *authGSSServerInit(PyObject *self, PyObject *args) { const char *service = NULL; gss_server_state *state; PyObject *pystate; int result = 0; if (!PyArg_ParseTuple(args, "s", &service)) return NULL; state = (gss_server_state *) malloc(sizeof(gss_server_state)); #if PY_MAJOR_VERSION >= 3 pystate = PyCapsule_New(state, NULL, NULL); #else pystate = PyCObject_FromVoidPtr(state, NULL); #endif result = authenticate_gss_server_init(service, state); if (result == AUTH_GSS_ERROR) return NULL; return Py_BuildValue("(iO)", result, pystate); } static PyObject *authGSSServerClean(PyObject *self, PyObject *args) { gss_server_state *state; PyObject *pystate; int result = 0; if (!PyArg_ParseTuple(args, "O", &pystate)) return NULL; #if PY_MAJOR_VERSION >= 3 if (!PyCapsule_CheckExact(pystate)) { #else if (!PyCObject_Check(pystate)) { #endif PyErr_SetString(PyExc_TypeError, "Expected a context object"); return NULL; } #if PY_MAJOR_VERSION >= 3 state = PyCapsule_GetPointer(pystate, NULL); #else state = (gss_client_state *)PyCObject_AsVoidPtr(pystate); #endif if (state != NULL) { result = authenticate_gss_server_clean(state); free(state); #if PY_MAJOR_VERSION >= 3 PyCapsule_SetPointer(pystate, NULL); #else PyCObject_SetVoidPtr(pystate, NULL); #endif } return Py_BuildValue("i", result); } static PyObject *authGSSServerStep(PyObject *self, PyObject *args) { gss_server_state *state; PyObject *pystate; char *challenge = NULL; int result = 0; if (!PyArg_ParseTuple(args, "Os", &pystate, &challenge)) return NULL; #if PY_MAJOR_VERSION >= 3 if (!PyCapsule_CheckExact(pystate)) { #else if (!PyCObject_Check(pystate)) { #endif PyErr_SetString(PyExc_TypeError, "Expected a context object"); return NULL; } #if PY_MAJOR_VERSION >= 3 state = PyCapsule_GetPointer(pystate, NULL); #else state = (gss_client_state *)PyCObject_AsVoidPtr(pystate); #endif if (state == NULL) return NULL; result = authenticate_gss_server_step(state, challenge); if (result == AUTH_GSS_ERROR) return NULL; return Py_BuildValue("i", result); } static PyObject *authGSSServerResponse(PyObject *self, PyObject *args) { gss_server_state *state; PyObject *pystate; if (!PyArg_ParseTuple(args, "O", &pystate)) return NULL; #if PY_MAJOR_VERSION >= 3 if (!PyCapsule_CheckExact(pystate)) { #else if (!PyCObject_Check(pystate)) { #endif PyErr_SetString(PyExc_TypeError, "Expected a context object"); return NULL; } #if PY_MAJOR_VERSION >= 3 state = PyCapsule_GetPointer(pystate, NULL); #else state = (gss_client_state *)PyCObject_AsVoidPtr(pystate); #endif if (state == NULL) return NULL; return Py_BuildValue("s", state->response); } static PyObject *authGSSServerUserName(PyObject *self, PyObject *args) { gss_server_state *state; PyObject *pystate; if (!PyArg_ParseTuple(args, "O", &pystate)) return NULL; #if PY_MAJOR_VERSION >= 3 if (!PyCapsule_CheckExact(pystate)) { #else if (!PyCObject_Check(pystate)) { #endif PyErr_SetString(PyExc_TypeError, "Expected a context object"); return NULL; } #if PY_MAJOR_VERSION >= 3 state = PyCapsule_GetPointer(pystate, NULL); #else state = (gss_client_state *)PyCObject_AsVoidPtr(pystate); #endif if (state == NULL) return NULL; return Py_BuildValue("s", state->username); } static PyObject *authGSSServerTargetName(PyObject *self, PyObject *args) { gss_server_state *state; PyObject *pystate; if (!PyArg_ParseTuple(args, "O", &pystate)) return NULL; #if PY_MAJOR_VERSION >= 3 if (!PyCapsule_CheckExact(pystate)) { #else if (!PyCObject_Check(pystate)) { #endif PyErr_SetString(PyExc_TypeError, "Expected a context object"); return NULL; } #if PY_MAJOR_VERSION >= 3 state = PyCapsule_GetPointer(pystate, NULL); #else state = (gss_client_state *)PyCObject_AsVoidPtr(pystate); #endif if (state == NULL) return NULL; return Py_BuildValue("s", state->targetname); } static PyMethodDef KerberosMethods[] = { {"checkPassword", checkPassword, METH_VARARGS, "Check the supplied user/password against Kerberos KDC."}, {"changePassword", changePassword, METH_VARARGS, "Change the user password."}, {"getServerPrincipalDetails", getServerPrincipalDetails, METH_VARARGS, "Return the service principal for a given service and hostname."}, {"authGSSClientInit", (PyCFunction)authGSSClientInit, METH_VARARGS | METH_KEYWORDS, "Initialize client-side GSSAPI operations."}, {"authGSSClientClean", authGSSClientClean, METH_VARARGS, "Terminate client-side GSSAPI operations."}, {"authGSSClientStep", authGSSClientStep, METH_VARARGS, "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, "Initialize server-side GSSAPI operations."}, {"authGSSClientWrap", authGSSClientWrap, METH_VARARGS, "Do a GSSAPI wrap."}, {"authGSSClientUnwrap", authGSSClientUnwrap, METH_VARARGS, "Do a GSSAPI unwrap."}, {"authGSSServerClean", authGSSServerClean, METH_VARARGS, "Terminate server-side GSSAPI operations."}, {"authGSSServerStep", authGSSServerStep, METH_VARARGS, "Do a server-side GSSAPI step."}, {"authGSSServerResponse", authGSSServerResponse, METH_VARARGS, "Get the response from the last server-side GSSAPI step."}, {"authGSSServerUserName", authGSSServerUserName, METH_VARARGS, "Get the user name from the last server-side GSSAPI step."}, {"authGSSServerTargetName", authGSSServerTargetName, METH_VARARGS, "Get the target name from the last server-side GSSAPI step."}, {NULL, NULL, 0, NULL} /* Sentinel */ }; #if PY_MAJOR_VERSION >= 3 static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "kerberos", /* m_name */ "High-level interface to kerberos", /* m_doc */ -1, /* m_size */ KerberosMethods, /* m_methods */ NULL, /* m_reload */ NULL, /* m_traverse */ NULL, /* m_clear */ NULL, /* m_free */ }; #endif #if PY_MAJOR_VERSION >= 3 PyObject* PyInit_kerberos(void) #else void initkerberos(void) #endif { PyObject *m,*d; #if PY_MAJOR_VERSION >= 3 m = PyModule_Create(&moduledef); #else m = Py_InitModule("kerberos", KerberosMethods); #endif d = PyModule_GetDict(m); /* create the base exception class */ if (!(KrbException_class = PyErr_NewException("kerberos.KrbError", NULL, NULL))) goto error; PyDict_SetItemString(d, "KrbError", KrbException_class); Py_INCREF(KrbException_class); /* ...and the derived exceptions */ if (!(BasicAuthException_class = PyErr_NewException("kerberos.BasicAuthError", KrbException_class, NULL))) goto error; Py_INCREF(BasicAuthException_class); PyDict_SetItemString(d, "BasicAuthError", BasicAuthException_class); if (!(PwdChangeException_class = PyErr_NewException("kerberos.PwdChangeError", KrbException_class, NULL))) goto error; Py_INCREF(PwdChangeException_class); PyDict_SetItemString(d, "PwdChangeError", PwdChangeException_class); if (!(GssException_class = PyErr_NewException("kerberos.GSSError", KrbException_class, NULL))) goto error; Py_INCREF(GssException_class); PyDict_SetItemString(d, "GSSError", GssException_class); PyDict_SetItemString(d, "AUTH_GSS_COMPLETE", PyInt_FromLong(AUTH_GSS_COMPLETE)); PyDict_SetItemString(d, "AUTH_GSS_CONTINUE", PyInt_FromLong(AUTH_GSS_CONTINUE)); PyDict_SetItemString(d, "GSS_C_DELEG_FLAG", PyInt_FromLong(GSS_C_DELEG_FLAG)); PyDict_SetItemString(d, "GSS_C_MUTUAL_FLAG", PyInt_FromLong(GSS_C_MUTUAL_FLAG)); PyDict_SetItemString(d, "GSS_C_REPLAY_FLAG", PyInt_FromLong(GSS_C_REPLAY_FLAG)); PyDict_SetItemString(d, "GSS_C_SEQUENCE_FLAG", PyInt_FromLong(GSS_C_SEQUENCE_FLAG)); PyDict_SetItemString(d, "GSS_C_CONF_FLAG", PyInt_FromLong(GSS_C_CONF_FLAG)); PyDict_SetItemString(d, "GSS_C_INTEG_FLAG", PyInt_FromLong(GSS_C_INTEG_FLAG)); PyDict_SetItemString(d, "GSS_C_ANON_FLAG", PyInt_FromLong(GSS_C_ANON_FLAG)); PyDict_SetItemString(d, "GSS_C_PROT_READY_FLAG", PyInt_FromLong(GSS_C_PROT_READY_FLAG)); PyDict_SetItemString(d, "GSS_C_TRANS_FLAG", PyInt_FromLong(GSS_C_TRANS_FLAG)); error: if (PyErr_Occurred()) PyErr_SetString(PyExc_ImportError, "kerberos: init failed"); #if PY_MAJOR_VERSION >= 3 return m; #endif } pykerberos-1.1.5/src/kerberosbasic.c0000644000076500000240000000757312314245233020072 0ustar stefanstaff00000000000000/** * 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. * 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. **/ #include #include "kerberosbasic.h" #include #include #include #undef PRINTFS 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); int authenticate_user_krb5pwd(const char *user, const char *pswd, const char *service, const char *default_realm) { krb5_context kcontext = NULL; krb5_error_code code; krb5_principal client = NULL; krb5_principal server = NULL; int ret = 0; char *name = NULL; char *p = NULL; code = krb5_init_context(&kcontext); 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) { set_basicauth_error(kcontext, ret); ret = 0; goto end; } code = krb5_unparse_name(kcontext, server, &name); 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(name); name = NULL; name = (char *)malloc(256); p = strchr(user, '@'); if (p == NULL) { snprintf(name, 256, "%s@%s", user, default_realm); } else { snprintf(name, 256, "%s", user); } code = krb5_parse_name(kcontext, name, &client); if (code) { set_basicauth_error(kcontext, code); ret = 0; goto end; } code = verify_krb5_user(kcontext, client, pswd, server); if (code) { ret = 0; goto end; } ret = 1; 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) krb5_free_principal(kcontext, client); if (server) krb5_free_principal(kcontext, server); krb5_free_context(kcontext); return ret; } /* 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) { krb5_creds creds; krb5_get_init_creds_opt gic_options; krb5_error_code ret; char *name = NULL; memset(&creds, 0, sizeof(creds)); ret = krb5_unparse_name(context, principal, &name); 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) { set_basicauth_error(context, ret); goto end; } end: krb5_free_cred_contents(context, &creds); return ret; } static void set_basicauth_error(krb5_context context, krb5_error_code code) { PyErr_SetObject(BasicAuthException_class, Py_BuildValue("(s:i)", krb5_get_err_text(context, code), code)); } pykerberos-1.1.5/src/kerberosbasic.h0000644000076500000240000000160212314245233020062 0ustar stefanstaff00000000000000/** * 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. * 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. **/ #include #include #include #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); pykerberos-1.1.5/src/kerberosgss.c0000644000076500000240000004772212314245233017605 0ustar stefanstaff00000000000000/** * 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. * 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. **/ #include #include "kerberosgss.h" #include "base64.h" #include #include #include #include static void set_gss_error(OM_uint32 err_maj, OM_uint32 err_min); extern PyObject *GssException_class; extern PyObject *KrbException_class; char* server_principal_details(const char* service, const char* hostname) { char match[1024]; size_t match_len = 0; char* result = NULL; int code; krb5_context kcontext; krb5_keytab kt = NULL; krb5_kt_cursor cursor = NULL; krb5_keytab_entry entry; char* pname = NULL; // Generate the principal prefix we want to match snprintf(match, 1024, "%s/%s@", service, hostname); match_len = strlen(match); code = krb5_init_context(&kcontext); if (code) { PyErr_SetObject(KrbException_class, Py_BuildValue("((s:i))", "Cannot initialize Kerberos5 context", code)); return NULL; } if ((code = krb5_kt_default(kcontext, &kt))) { PyErr_SetObject(KrbException_class, Py_BuildValue("((s:i))", "Cannot get default keytab", code)); goto end; } if ((code = krb5_kt_start_seq_get(kcontext, kt, &cursor))) { PyErr_SetObject(KrbException_class, Py_BuildValue("((s:i))", "Cannot get sequence cursor from keytab", code)); goto end; } while ((code = krb5_kt_next_entry(kcontext, kt, &entry, &cursor)) == 0) { if ((code = krb5_unparse_name(kcontext, entry.principal, &pname))) { PyErr_SetObject(KrbException_class, Py_BuildValue("((s:i))", "Cannot parse principal name from keytab", code)); goto end; } if (strncmp(pname, match, match_len) == 0) { result = malloc(strlen(pname) + 1); strcpy(result, pname); krb5_free_unparsed_name(kcontext, pname); krb5_free_keytab_entry_contents(kcontext, &entry); break; } krb5_free_unparsed_name(kcontext, pname); krb5_free_keytab_entry_contents(kcontext, &entry); } if (result == NULL) { PyErr_SetObject(KrbException_class, Py_BuildValue("((s:i))", "Principal not found in keytab", -1)); } end: if (cursor) krb5_kt_end_seq_get(kcontext, kt, &cursor); if (kt) krb5_kt_close(kcontext, kt); krb5_free_context(kcontext); return result; } 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; // Import server name first name_token.length = strlen(service); name_token.value = (char *)service; maj_stat = gss_import_name(&min_stat, &name_token, gss_krb5_nt_service_name, &state->server_name); if (GSS_ERROR(maj_stat)) { set_gss_error(maj_stat, min_stat); ret = AUTH_GSS_ERROR; 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; } int authenticate_gss_client_clean(gss_client_state *state) { OM_uint32 maj_stat; OM_uint32 min_stat; int ret = AUTH_GSS_COMPLETE; if (state->context != GSS_C_NO_CONTEXT) 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); state->username = NULL; } if (state->response != NULL) { free(state->response); state->response = NULL; } return ret; } int authenticate_gss_client_step(gss_client_state* state, const char* challenge) { OM_uint32 maj_stat; OM_uint32 min_stat; gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; int ret = AUTH_GSS_CONTINUE; // Always clear out the old response if (state->response != NULL) { free(state->response); state->response = NULL; } // If there is a challenge (data from the server) we need to give it to GSS if (challenge && *challenge) { 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, state->client_creds, &state->context, state->server_name, GSS_C_NO_OID, (OM_uint32)state->gss_flags, 0, GSS_C_NO_CHANNEL_BINDINGS, &input_token, NULL, &output_token, NULL, NULL); Py_END_ALLOW_THREADS if ((maj_stat != GSS_S_COMPLETE) && (maj_stat != GSS_S_CONTINUE_NEEDED)) { set_gss_error(maj_stat, min_stat); ret = AUTH_GSS_ERROR; goto end; } ret = (maj_stat == GSS_S_COMPLETE) ? AUTH_GSS_COMPLETE : AUTH_GSS_CONTINUE; // Grab the client response to send back to the server if (output_token.length) { state->response = base64_encode((const unsigned char *)output_token.value, output_token.length);; maj_stat = gss_release_buffer(&min_stat, &output_token); } // Try to get the user name if we have completed all GSS operations if (ret == AUTH_GSS_COMPLETE) { gss_name_t gssuser = GSS_C_NO_NAME; maj_stat = gss_inquire_context(&min_stat, state->context, &gssuser, NULL, NULL, NULL, NULL, NULL, NULL); if (GSS_ERROR(maj_stat)) { set_gss_error(maj_stat, min_stat); ret = AUTH_GSS_ERROR; goto end; } gss_buffer_desc name_token; name_token.length = 0; maj_stat = gss_display_name(&min_stat, gssuser, &name_token, NULL); if (GSS_ERROR(maj_stat)) { if (name_token.value) gss_release_buffer(&min_stat, &name_token); gss_release_name(&min_stat, &gssuser); set_gss_error(maj_stat, min_stat); ret = AUTH_GSS_ERROR; goto end; } else { state->username = (char *)malloc(name_token.length + 1); strncpy(state->username, (char*) name_token.value, name_token.length); state->username[name_token.length] = 0; gss_release_buffer(&min_stat, &name_token); gss_release_name(&min_stat, &gssuser); } } end: if (output_token.value) gss_release_buffer(&min_stat, &output_token); if (input_token.value) free(input_token.value); return ret; } int authenticate_gss_client_unwrap(gss_client_state *state, const char *challenge) { OM_uint32 maj_stat; OM_uint32 min_stat; 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) { size_t len; input_token.value = base64_decode(challenge, &len); input_token.length = len; } // Do GSSAPI step maj_stat = gss_unwrap(&min_stat, state->context, &input_token, &output_token, &conf, NULL); if (maj_stat != GSS_S_COMPLETE) { set_gss_error(maj_stat, min_stat); ret = AUTH_GSS_ERROR; goto end; } else ret = AUTH_GSS_COMPLETE; // Grab the client response 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: if (output_token.value) gss_release_buffer(&min_stat, &output_token); if (input_token.value) free(input_token.value); return ret; } 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; gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; int ret = AUTH_GSS_CONTINUE; char buf[4096], server_conf_flags; unsigned long buf_size; // Always clear out the old response if (state->response != NULL) { free(state->response); state->response = NULL; } if (challenge && *challenge) { size_t len; input_token.value = base64_decode(challenge, &len); input_token.length = len; } if (user) { // get bufsize server_conf_flags = ((char*) input_token.value)[0]; ((char*) input_token.value)[0] = 0; buf_size = ntohl(*((long *) input_token.value)); free(input_token.value); #ifdef PRINTFS printf("User: %s, %c%c%c\n", user, server_conf_flags & GSS_AUTH_P_NONE ? 'N' : '-', server_conf_flags & GSS_AUTH_P_INTEGRITY ? 'I' : '-', server_conf_flags & GSS_AUTH_P_PRIVACY ? 'P' : '-'); printf("Maximum GSS token size is %ld\n", buf_size); #endif // agree to terms (hack!) buf_size = htonl(buf_size); // not relevant without integrity/privacy memcpy(buf, &buf_size, 4); buf[0] = GSS_AUTH_P_NONE; // server decides if principal can log in as user strncpy(buf + 4, user, sizeof(buf) - 4); input_token.value = buf; input_token.length = 4 + strlen(user); } // Do GSSAPI wrap maj_stat = gss_wrap(&min_stat, state->context, protect, GSS_C_QOP_DEFAULT, &input_token, NULL, &output_token); if (maj_stat != GSS_S_COMPLETE) { set_gss_error(maj_stat, min_stat); ret = AUTH_GSS_ERROR; goto end; } else ret = AUTH_GSS_COMPLETE; // Grab the client response to send back to the server if (output_token.length) { state->response = base64_encode((const unsigned char *)output_token.value, output_token.length);; maj_stat = gss_release_buffer(&min_stat, &output_token); } end: if (output_token.value) gss_release_buffer(&min_stat, &output_token); return ret; } int authenticate_gss_server_init(const char *service, gss_server_state *state) { OM_uint32 maj_stat; OM_uint32 min_stat; gss_buffer_desc name_token = GSS_C_EMPTY_BUFFER; int ret = AUTH_GSS_COMPLETE; state->context = GSS_C_NO_CONTEXT; state->server_name = GSS_C_NO_NAME; state->client_name = GSS_C_NO_NAME; state->server_creds = GSS_C_NO_CREDENTIAL; state->client_creds = GSS_C_NO_CREDENTIAL; state->username = NULL; state->targetname = NULL; state->response = NULL; // Server name may be empty which means we aren't going to create our own creds size_t service_len = strlen(service); if (service_len != 0) { // Import server name first name_token.length = strlen(service); name_token.value = (char *)service; maj_stat = gss_import_name(&min_stat, &name_token, GSS_C_NT_HOSTBASED_SERVICE, &state->server_name); if (GSS_ERROR(maj_stat)) { set_gss_error(maj_stat, min_stat); ret = AUTH_GSS_ERROR; goto end; } // Get credentials maj_stat = gss_acquire_cred(&min_stat, state->server_name, GSS_C_INDEFINITE, GSS_C_NO_OID_SET, GSS_C_ACCEPT, &state->server_creds, NULL, NULL); if (GSS_ERROR(maj_stat)) { set_gss_error(maj_stat, min_stat); ret = AUTH_GSS_ERROR; goto end; } } end: return ret; } int authenticate_gss_server_clean(gss_server_state *state) { OM_uint32 maj_stat; OM_uint32 min_stat; int ret = AUTH_GSS_COMPLETE; if (state->context != GSS_C_NO_CONTEXT) 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_name != GSS_C_NO_NAME) maj_stat = gss_release_name(&min_stat, &state->client_name); if (state->server_creds != GSS_C_NO_CREDENTIAL) maj_stat = gss_release_cred(&min_stat, &state->server_creds); 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); state->username = NULL; } if (state->targetname != NULL) { free(state->targetname); state->targetname = NULL; } if (state->response != NULL) { free(state->response); state->response = NULL; } return ret; } int authenticate_gss_server_step(gss_server_state *state, const char *challenge) { OM_uint32 maj_stat; OM_uint32 min_stat; gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; int ret = AUTH_GSS_CONTINUE; // Always clear out the old response if (state->response != NULL) { free(state->response); state->response = NULL; } // If there is a challenge (data from the server) we need to give it to GSS if (challenge && *challenge) { size_t len; input_token.value = base64_decode(challenge, &len); input_token.length = len; } else { PyErr_SetString(KrbException_class, "No challenge parameter in request from client"); ret = AUTH_GSS_ERROR; goto end; } Py_BEGIN_ALLOW_THREADS maj_stat = gss_accept_sec_context(&min_stat, &state->context, state->server_creds, &input_token, GSS_C_NO_CHANNEL_BINDINGS, &state->client_name, NULL, &output_token, NULL, NULL, &state->client_creds); Py_END_ALLOW_THREADS if (GSS_ERROR(maj_stat)) { set_gss_error(maj_stat, min_stat); ret = AUTH_GSS_ERROR; goto end; } // Grab the server response to send back to the client if (output_token.length) { state->response = base64_encode((const unsigned char *)output_token.value, output_token.length);; maj_stat = gss_release_buffer(&min_stat, &output_token); } // Get the user name maj_stat = gss_display_name(&min_stat, state->client_name, &output_token, NULL); if (GSS_ERROR(maj_stat)) { set_gss_error(maj_stat, min_stat); ret = AUTH_GSS_ERROR; goto end; } state->username = (char *)malloc(output_token.length + 1); strncpy(state->username, (char*) output_token.value, output_token.length); state->username[output_token.length] = 0; // Get the target name if no server creds were supplied if (state->server_creds == GSS_C_NO_CREDENTIAL) { gss_name_t target_name = GSS_C_NO_NAME; maj_stat = gss_inquire_context(&min_stat, state->context, NULL, &target_name, NULL, NULL, NULL, NULL, NULL); if (GSS_ERROR(maj_stat)) { set_gss_error(maj_stat, min_stat); ret = AUTH_GSS_ERROR; goto end; } maj_stat = gss_display_name(&min_stat, target_name, &output_token, NULL); if (GSS_ERROR(maj_stat)) { set_gss_error(maj_stat, min_stat); ret = AUTH_GSS_ERROR; goto end; } state->targetname = (char *)malloc(output_token.length + 1); strncpy(state->targetname, (char*) output_token.value, output_token.length); state->targetname[output_token.length] = 0; } ret = AUTH_GSS_COMPLETE; end: if (output_token.length) gss_release_buffer(&min_stat, &output_token); if (input_token.value) free(input_token.value); return ret; } static void set_gss_error(OM_uint32 err_maj, OM_uint32 err_min) { OM_uint32 maj_stat, min_stat; OM_uint32 msg_ctx = 0; gss_buffer_desc status_string; char buf_maj[512]; char buf_min[512]; do { maj_stat = gss_display_status (&min_stat, err_maj, GSS_C_GSS_CODE, GSS_C_NO_OID, &msg_ctx, &status_string); if (GSS_ERROR(maj_stat)) break; strncpy(buf_maj, (char*) status_string.value, sizeof(buf_maj)); gss_release_buffer(&min_stat, &status_string); maj_stat = gss_display_status (&min_stat, err_min, GSS_C_MECH_CODE, GSS_C_NULL_OID, &msg_ctx, &status_string); if (!GSS_ERROR(maj_stat)) { strncpy(buf_min, (char*) status_string.value, sizeof(buf_min)); gss_release_buffer(&min_stat, &status_string); } } while (!GSS_ERROR(maj_stat) && msg_ctx != 0); PyErr_SetObject(GssException_class, Py_BuildValue("((s:i)(s:i))", buf_maj, err_maj, buf_min, err_min)); } pykerberos-1.1.5/src/kerberosgss.h0000644000076500000240000000440412314245233017600 0ustar stefanstaff00000000000000/** * 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. * 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. **/ #include #include #include #define krb5_get_err_text(context,code) error_message(code) #define AUTH_GSS_ERROR -1 #define AUTH_GSS_COMPLETE 1 #define AUTH_GSS_CONTINUE 0 #define GSS_AUTH_P_NONE 1 #define GSS_AUTH_P_INTEGRITY 2 #define GSS_AUTH_P_PRIVACY 4 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 { gss_ctx_id_t context; gss_name_t server_name; gss_name_t client_name; gss_cred_id_t server_creds; gss_cred_id_t client_creds; char* username; char* targetname; char* response; } gss_server_state; 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_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); 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); pykerberos-1.1.5/src/kerberospw.c0000644000076500000240000001047612314245233017433 0ustar stefanstaff00000000000000/** * Copyright (c) 2008 Guido Guenther * * 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. **/ #include #include "kerberospw.h" #include #include #include #undef PRINTFS extern PyObject *PwdChangeException_class; static void set_pwchange_error(krb5_context context, krb5_error_code code) { PyErr_SetObject(PwdChangeException_class, Py_BuildValue("(s:i)", krb5_get_err_text(context, code), code)); } /* Inspired by krb5_verify_user from Heimdal */ static krb5_error_code verify_krb5_user(krb5_context context, krb5_principal principal, const char *password, const char *service, krb5_creds* creds) { krb5_get_init_creds_opt gic_options; krb5_error_code code; int ret = 0; #ifdef PRINTFS { char *name = NULL; code = krb5_unparse_name(context, principal, &name); if (!code) printf("Trying to get TGT for user %s\n", name); free(name); } #endif krb5_get_init_creds_opt_init(&gic_options); krb5_get_init_creds_opt_set_forwardable(&gic_options, 0); krb5_get_init_creds_opt_set_proxiable(&gic_options, 0); 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); if (code) { set_pwchange_error(context, code); goto end; } ret = 1; /* success */ end: return ret; } int change_user_krb5pwd(const char *user, const char* oldpswd, const char *newpswd) { krb5_context kcontext = NULL; krb5_error_code code; krb5_principal client = NULL; krb5_creds creds; int ret = 0; char *name = NULL; const char* service = "kadmin/changepw"; int result_code; krb5_data result_code_string, result_string; code = krb5_init_context(&kcontext); if (code) { PyErr_SetObject(PwdChangeException_class, Py_BuildValue("((s:i))", "Cannot initialize Kerberos5 context", code)); return 0; } name = (char *)malloc(256); snprintf(name, 256, "%s", user); code = krb5_parse_name(kcontext, name, &client); if (code) { set_pwchange_error(kcontext, code); goto end; } code = verify_krb5_user(kcontext, client, oldpswd, service, &creds); if (!code) /* exception set by verify_krb5_user */ goto end; code = krb5_change_password(kcontext, &creds, (char*)newpswd, &result_code, &result_code_string, &result_string); if (code) { set_pwchange_error(kcontext, code); goto end; } if (result_code) { char *message = NULL; 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))", message, result_code)); free(message); goto end; } ret = 1; /* success */ end: #ifdef PRINTFS printf("%s: ret=%d user=%s\n", __FUNCTION__, ret, name); #endif if (name) free(name); if (client) krb5_free_principal(kcontext, client); krb5_free_context(kcontext); return ret; } pykerberos-1.1.5/src/kerberospw.h0000644000076500000240000000154312314245233017433 0ustar stefanstaff00000000000000/** * Copyright (c) 2008 Guido Guenther * * 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. * **/ #include #include #include #define krb5_get_err_text(context,code) error_message(code) int change_user_krb5pwd(const char *user, const char* oldpswd, const char *newpswd);