#!/usr/bin/python2.7 # -*- coding: utf-8 -*- # # Univention RADIUS 802.1X # NTLM-Authentication program # # Copyright (C) 2012-2015 Univention GmbH # # http://www.univention.de/ # # All rights reserved. # # The source code of the software contained in this package # as well as the source package itself are made available # under the terms of the GNU Affero General Public License version 3 # (GNU AGPL V3) as published by the Free Software Foundation. # # Binary versions of this package provided by Univention to you as # well as other copyrighted, protected or trademarked materials like # Logos, graphics, fonts, specific documentations and configurations, # cryptographic keys etc. are subject to a license agreement between # you and Univention and not subject to the GNU AGPL V3. # # In the case you use the software under the terms of the GNU AGPL V3, # the program is provided in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public # License with the Debian GNU/Linux or Univention distribution in file # /usr/share/common-licenses/AGPL-3; if not, see # . from univention.networkaccess import getNTPasswordHash import optparse import sys import univention.pyMsChapV2 as pyMsChapV2 import univention.uldap from ldap import SERVER_DOWN def main(): parser = optparse.OptionParser() parser.add_option('--request-nt-key', action='store_true', dest='requestNtKey') parser.add_option('--username', dest='Username') parser.add_option('--challenge', dest='Challenge') parser.add_option('--nt-response', dest='Response') parser.add_option('--station-id', dest='stationId') (options, args, ) = parser.parse_args() if not options.requestNtKey: print 'Missing required parameter --request-nt-key!' return 1 if not options.Username: print 'Missing required parameter --username!' return 1 if not options.Challenge: print 'Missing required parameter --challenge!' return 1 if not options.Response: print 'Missing required parameter --nt-response!' return 1 if not options.stationId: stationId = None else: # safely decode station id (fails with exception on mis-formatted id, thus returning 1) debug_file = open("/tmp/radius-debug.txt", "a") debug_file.write("Supplied station ID: >%s<\n" % options.stationId) debug_file.close() stationId = options.stationId stationId = stationId[0:2] + stationId[3:5] + stationId[6:8] + stationId[9:11] + stationId[12:14] + stationId[15:17] stationId = stationId.decode('hex') options.Challenge = options.Challenge.decode('hex') options.Response = options.Response.decode('hex') try: # try ldap/server/name, then each of ldap/server/addition ldapConnection = univention.uldap.getMachineConnection(ldap_master=False, reconnect=False) except SERVER_DOWN: # then master dc ldapConnection = univention.uldap.getMachineConnection() PasswordHash = getNTPasswordHash(ldapConnection, options.Username, stationId) if PasswordHash and pyMsChapV2.ChallengeResponse(options.Challenge, PasswordHash) == options.Response: print 'NT_KEY: %s' % (pyMsChapV2.HashNtPasswordHash(PasswordHash).encode('hex').upper(), ) return 0 else: print 'Logon failure (0xc000006d)' return 1 if __name__ == "__main__": sys.exit(main())