Search
SailfishOS Open Build Service
>
Projects
>
home:kontio
:
nfs
>
cyrus-sasl
> cyrus-sasl-2.1.22-no-dlcompatorsrp.patch
Log In
Username
Password
Cancel
Overview
Repositories
Revisions
Requests
Users
Advanced
Attributes
Meta
File cyrus-sasl-2.1.22-no-dlcompatorsrp.patch of Package cyrus-sasl
diff -urN cyrus-sasl-2.1.22/dlcompat-20010505/APPLE_LICENSE cyrus-sasl-2.1.22-no/dlcompat-20010505/APPLE_LICENSE --- cyrus-sasl-2.1.22/dlcompat-20010505/APPLE_LICENSE 2001-08-04 06:09:32.000000000 +0800 +++ cyrus-sasl-2.1.22-no/dlcompat-20010505/APPLE_LICENSE 1970-01-01 08:00:00.000000000 +0800 @@ -1,372 +0,0 @@ -APPLE PUBLIC SOURCE LICENSE -Version 1.1 - April 19,1999 - -Please read this License carefully before downloading this software. -By downloading and using this software, you are agreeing to be bound -by the terms of this License. If you do not or cannot agree to the -terms of this License, please do not download or use the software. - -1. General; Definitions. This License applies to any program or other -work which Apple Computer, Inc. ("Apple") publicly announces as -subject to this Apple Public Source License and which contains a -notice placed by Apple identifying such program or work as "Original -Code" and stating that it is subject to the terms of this Apple Public -Source License version 1.1 (or subsequent version thereof), as it may -be revised from time to time by Apple ("License"). As used in this -License: - -1.1 "Affected Original Code" means only those specific portions of -Original Code that allegedly infringe upon any party's intellectual -property rights or are otherwise the subject of a claim of -infringement. - -1.2 "Applicable Patent Rights" mean: (a) in the case where Apple is -the grantor of rights, (i) claims of patents that are now or hereafter -acquired, owned by or assigned to Apple and (ii) that cover subject -matter contained in the Original Code, but only to the extent -necessary to use, reproduce and/or distribute the Original Code -without infringement; and (b) in the case where You are the grantor of -rights, (i) claims of patents that are now or hereafter acquired, -owned by or assigned to You and (ii) that cover subject matter in Your -Modifications, taken alone or in combination with Original Code. - -1.3 "Covered Code" means the Original Code, Modifications, the -combination of Original Code and any Modifications, and/or any -respective portions thereof. - -1.4 "Deploy" means to use, sublicense or distribute Covered Code other -than for Your internal research and development (R&D), and includes -without limitation, any and all internal use or distribution of -Covered Code within Your business or organization except for R&D use, -as well as direct or indirect sublicensing or distribution of Covered -Code by You to any third party in any form or manner. - -1.5 "Larger Work" means a work which combines Covered Code or portions -thereof with code not governed by the terms of this License. - -1.6 "Modifications" mean any addition to, deletion from, and/or change -to, the substance and/or structure of Covered Code. When code is -released as a series of files, a Modification is: (a) any addition to -or deletion from the contents of a file containing Covered Code; -and/or (b) any new file or other representation of computer program -statements that contains any part of Covered Code. - -1.7 "Original Code" means (a) the Source Code of a program or other -work as originally made available by Apple under this License, -including the Source Code of any updates or upgrades to such programs -or works made available by Apple under this License, and that has been -expressly identified by Apple as such in the header file(s) of such -work; and (b) the object code compiled from such Source Code and -originally made available by Apple under this License. - -1.8 "Source Code" means the human readable form of a program or other -work that is suitable for making modifications to it, including all -modules it contains, plus any associated interface definition files, -scripts used to control compilation and installation of an executable -(object code). - -1.9 "You" or "Your" means an individual or a legal entity exercising -rights under this License. For legal entities, "You" or "Your" -includes any entity which controls, is controlled by, or is under -common control with, You, where "control" means (a) the power, direct -or indirect, to cause the direction or management of such entity, -whether by contract or otherwise, or (b) ownership of fifty percent -(50%) or more of the outstanding shares or beneficial ownership of -such entity. - -2. Permitted Uses; Conditions & Restrictions. Subject to the terms -and conditions of this License, Apple hereby grants You, effective on -the date You accept this License and download the Original Code, a -world-wide, royalty-free, non- exclusive license, to the extent of -Apple's Applicable Patent Rights and copyrights covering the Original -Code, to do the following: - -2.1 You may use, copy, modify and distribute Original Code, with or -without Modifications, solely for Your internal research and -development, provided that You must in each instance: - -(a) retain and reproduce in all copies of Original Code the copyright -and other proprietary notices and disclaimers of Apple as they appear -in the Original Code, and keep intact all notices in the Original Code -that refer to this License; - -(b) include a copy of this License with every copy of Source Code of -Covered Code and documentation You distribute, and You may not offer -or impose any terms on such Source Code that alter or restrict this -License or the recipients' rights hereunder, except as permitted under -Section 6; and - -(c) completely and accurately document all Modifications that you have -made and the date of each such Modification, designate the version of -the Original Code you used, prominently include a file carrying such -information with the Modifications, and duplicate the notice in -Exhibit A in each file of the Source Code of all such Modifications. - -2.2 You may Deploy Covered Code, provided that You must in each - instance: - -(a) satisfy all the conditions of Section 2.1 with respect to the -Source Code of the Covered Code; - -(b) make all Your Deployed Modifications publicly available in Source -Code form via electronic distribution (e.g. download from a web site) -under the terms of this License and subject to the license grants set -forth in Section 3 below, and any additional terms You may choose to -offer under Section 6. You must continue to make the Source Code of -Your Deployed Modifications available for as long as you Deploy the -Covered Code or twelve (12) months from the date of initial -Deployment, whichever is longer; - -(c) if You Deploy Covered Code containing Modifications made by You, -inform others of how to obtain those Modifications by filling out and -submitting the information found at -http://www.apple.com/publicsource/modifications.html, if available; -and - -(d) if You Deploy Covered Code in object code, executable form only, -include a prominent notice, in the code itself as well as in related -documentation, stating that Source Code of the Covered Code is -available under the terms of this License with information on how and -where to obtain such Source Code. - -3. Your Grants. In consideration of, and as a condition to, the -licenses granted to You under this License: - -(a) You hereby grant to Apple and all third parties a non-exclusive, -royalty-free license, under Your Applicable Patent Rights and other -intellectual property rights owned or controlled by You, to use, -reproduce, modify, distribute and Deploy Your Modifications of the -same scope and extent as Apple's licenses under Sections 2.1 and 2.2; -and - -(b) You hereby grant to Apple and its subsidiaries a non-exclusive, -worldwide, royalty-free, perpetual and irrevocable license, under Your -Applicable Patent Rights and other intellectual property rights owned -or controlled by You, to use, reproduce, execute, compile, display, -perform, modify or have modified (for Apple and/or its subsidiaries), -sublicense and distribute Your Modifications, in any form, through -multiple tiers of distribution. - -4. Larger Works. You may create a Larger Work by combining Covered -Code with other code not governed by the terms of this License and -distribute the Larger Work as a single product. In each such -instance, You must make sure the requirements of this License are -fulfilled for the Covered Code or any portion thereof. - -5. Limitations on Patent License. Except as expressly stated in -Section 2, no other patent rights, express or implied, are granted by -Apple herein. Modifications and/or Larger Works may require -additional patent licenses from Apple which Apple may grant in its -sole discretion. - -6. Additional Terms. You may choose to offer, and to charge a fee -for, warranty, support, indemnity or liability obligations and/or -other rights consistent with the scope of the license granted herein -("Additional Terms") to one or more recipients of Covered -Code. However, You may do so only on Your own behalf and as Your sole -responsibility, and not on behalf of Apple. You must obtain the -recipient's agreement that any such Additional Terms are offered by -You alone, and You hereby agree to indemnify, defend and hold Apple -harmless for any liability incurred by or claims asserted against -Apple by reason of any such Additional Terms. - -7. Versions of the License. Apple may publish revised and/or new -versions of this License from time to time. Each version will be -given a distinguishing version number. Once Original Code has been -published under a particular version of this License, You may continue -to use it under the terms of that version. You may also choose to use -such Original Code under the terms of any subsequent version of this -License published by Apple. No one other than Apple has the right to -modify the terms applicable to Covered Code created under this -License. - -8. NO WARRANTY OR SUPPORT. The Original Code may contain in whole or -in part pre-release, untested, or not fully tested works. The -Original Code may contain errors that could cause failures or loss of -data, and may be incomplete or contain inaccuracies. You expressly -acknowledge and agree that use of the Original Code, or any portion -thereof, is at Your sole and entire risk. THE ORIGINAL CODE IS -PROVIDED "AS IS" AND WITHOUT WARRANTY, UPGRADES OR SUPPORT OF ANY KIND -AND APPLE AND APPLE'S LICENSOR(S) (FOR THE PURPOSES OF SECTIONS 8 AND -9, APPLE AND APPLE'S LICENSOR(S) ARE COLLECTIVELY REFERRED TO AS -"APPLE") EXPRESSLY DISCLAIM ALL WARRANTIES AND/OR CONDITIONS, EXPRESS -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -AND/OR CONDITIONS OF MERCHANTABILITY OR SATISFACTORY QUALITY AND -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY -RIGHTS. APPLE DOES NOT WARRANT THAT THE FUNCTIONS CONTAINED IN THE -ORIGINAL CODE WILL MEET YOUR REQUIREMENTS, OR THAT THE OPERATION OF -THE ORIGINAL CODE WILL BE UNINTERRUPTED OR ERROR- FREE, OR THAT -DEFECTS IN THE ORIGINAL CODE WILL BE CORRECTED. NO ORAL OR WRITTEN -INFORMATION OR ADVICE GIVEN BY APPLE OR AN APPLE AUTHORIZED -REPRESENTATIVE SHALL CREATE A WARRANTY OR IN ANY WAY INCREASE THE -SCOPE OF THIS WARRANTY. You acknowledge that the Original Code is not -intended for use in the operation of nuclear facilities, aircraft -navigation, communication systems, or air traffic control machines in -which case the failure of the Original Code could lead to death, -personal injury, or severe physical or environmental damage. - -9. Liability. - -9.1 Infringement. If any portion of, or functionality implemented by, -the Original Code becomes the subject of a claim of infringement, -Apple may, at its option: (a) attempt to procure the rights necessary -for Apple and You to continue using the Affected Original Code; (b) -modify the Affected Original Code so that it is no longer infringing; -or (c) suspend Your rights to use, reproduce, modify, sublicense and -distribute the Affected Original Code until a final determination of -the claim is made by a court or governmental administrative agency of -competent jurisdiction and Apple lifts the suspension as set forth -below. Such suspension of rights will be effective immediately upon -Apple's posting of a notice to such effect on the Apple web site that -is used for implementation of this License. Upon such final -determination being made, if Apple is legally able, without the -payment of a fee or royalty, to resume use, reproduction, -modification, sublicensing and distribution of the Affected Original -Code, Apple will lift the suspension of rights to the Affected -Original Code by posting a notice to such effect on the Apple web site -that is used for implementation of this License. If Apple suspends -Your rights to Affected Original Code, nothing in this License shall -be construed to restrict You, at Your option and subject to applicable -law, from replacing the Affected Original Code with non-infringing -code or independently negotiating for necessary rights from such third -party. - -9.2 LIMITATION OF LIABILITY. UNDER NO CIRCUMSTANCES SHALL APPLE BE -LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES -ARISING OUT OF OR RELATING TO THIS LICENSE OR YOUR USE OR INABILITY TO -USE THE ORIGINAL CODE, OR ANY PORTION THEREOF, WHETHER UNDER A THEORY -OF CONTRACT, WARRANTY, TORT (INCLUDING NEGLIGENCE), PRODUCTS LIABILITY -OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES AND NOTWITHSTANDING THE FAILURE OF ESSENTIAL PURPOSE OF -ANY REMEDY. In no event shall Apple's total liability to You for all -damages under this License exceed the amount of fifty dollars -($50.00). - -10. Trademarks. This License does not grant any rights to use the -trademarks or trade names "Apple", "Apple Computer", "Mac OS X", "Mac -OS X Server" or any other trademarks or trade names belonging to Apple -(collectively "Apple Marks") and no Apple Marks may be used to endorse -or promote products derived from the Original Code other than as -permitted by and in strict compliance at all times with Apple's third -party trademark usage guidelines which are posted at -http://www.apple.com/legal/guidelinesfor3rdparties.html. - -11. Ownership. Apple retains all rights, title and interest in and to -the Original Code and any Modifications made by or on behalf of Apple -("Apple Modifications"), and such Apple Modifications will not be -automatically subject to this License. Apple may, at its sole -discretion, choose to license such Apple Modifications under this -License, or on different terms from those contained in this License or -may choose not to license them at all. Apple's development, use, -reproduction, modification, sublicensing and distribution of Covered -Code will not be subject to this License. - -12. Termination. - -12.1 Termination. This License and the rights granted hereunder will - terminate: - -(a) automatically without notice from Apple if You fail to comply with -any term(s) of this License and fail to cure such breach within 30 -days of becoming aware of such breach; (b) immediately in the event of -the circumstances described in Section 13.5(b); or (c) automatically -without notice from Apple if You, at any time during the term of this -License, commence an action for patent infringement against Apple. - -12.2 Effect of Termination. Upon termination, You agree to -immediately stop any further use, reproduction, modification, -sublicensing and distribution of the Covered Code and to destroy all -copies of the Covered Code that are in your possession or control. -All sublicenses to the Covered Code which have been properly granted -prior to termination shall survive any termination of this License. -Provisions which, by their nature, should remain in effect beyond the -termination of this License shall survive, including but not limited -to Sections 3, 5, 8, 9, 10, 11, 12.2 and 13. Neither party will be -liable to the other for compensation, indemnity or damages of any sort -solely as a result of terminating this License in accordance with its -terms, and termination of this License will be without prejudice to -any other right or remedy of either party. - -13. Miscellaneous. - -13.1 Government End Users. The Covered Code is a "commercial item" as -defined in FAR 2.101. Government software and technical data rights -in the Covered Code include only those rights customarily provided to -the public as defined in this License. This customary commercial -license in technical data and software is provided in accordance with -FAR 12.211 (Technical Data) and 12.212 (Computer Software) and, for -Department of Defense purchases, DFAR 252.227-7015 (Technical Data -- -Commercial Items) and 227.7202-3 (Rights in Commercial Computer -Software or Computer Software Documentation). Accordingly, all U.S. -Government End Users acquire Covered Code with only those rights set -forth herein. - -13.2 Relationship of Parties. This License will not be construed as -creating an agency, partnership, joint venture or any other form of -legal association between You and Apple, and You will not represent to -the contrary, whether expressly, by implication, appearance or -otherwise. - -13.3 Independent Development. Nothing in this License will impair -Apple's right to acquire, license, develop, have others develop for -it, market and/or distribute technology or products that perform the -same or similar functions as, or otherwise compete with, -Modifications, Larger Works, technology or products that You may -develop, produce, market or distribute. - -13.4 Waiver; Construction. Failure by Apple to enforce any provision -of this License will not be deemed a waiver of future enforcement of -that or any other provision. Any law or regulation which provides -that the language of a contract shall be construed against the drafter -will not apply to this License. - -13.5 Severability. (a) If for any reason a court of competent -jurisdiction finds any provision of this License, or portion thereof, -to be unenforceable, that provision of the License will be enforced to -the maximum extent permissible so as to effect the economic benefits -and intent of the parties, and the remainder of this License will -continue in full force and effect. (b) Notwithstanding the foregoing, -if applicable law prohibits or restricts You from fully and/or -specifically complying with Sections 2 and/or 3 or prevents the -enforceability of either of those Sections, this License will -immediately terminate and You must immediately discontinue any use of -the Covered Code and destroy all copies of it that are in your -possession or control. - -13.6 Dispute Resolution. Any litigation or other dispute resolution -between You and Apple relating to this License shall take place in the -Northern District of California, and You and Apple hereby consent to -the personal jurisdiction of, and venue in, the state and federal -courts within that District with respect to this License. The -application of the United Nations Convention on Contracts for the -International Sale of Goods is expressly excluded. - -13.7 Entire Agreement; Governing Law. This License constitutes the -entire agreement between the parties with respect to the subject -matter hereof. This License shall be governed by the laws of the -United States and the State of California, except that body of -California law concerning conflicts of law. - -Where You are located in the province of Quebec, Canada, the following -clause applies: The parties hereby confirm that they have requested -that this License and all related documents be drafted in English. Les -parties ont exige que le present contrat et tous les documents -connexes soient rediges en anglais. - -EXHIBIT A. - -"Portions Copyright (c) 1999 Apple Computer, Inc. All Rights -Reserved. This file contains Original Code and/or Modifications of -Original Code as defined in and that are subject to the Apple Public -Source License Version 1.1 (the "License"). You may not use this file -except in compliance with the License. Please obtain a copy of the -License at http://www.apple.com/publicsource and read it before using -this file. - -The Original Code and all software distributed under the License are -distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER -EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, -INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the -License for the specific language governing rights and limitations -under the License." diff -urN cyrus-sasl-2.1.22/dlcompat-20010505/ChangeLog cyrus-sasl-2.1.22-no/dlcompat-20010505/ChangeLog --- cyrus-sasl-2.1.22/dlcompat-20010505/ChangeLog 2001-08-04 06:09:32.000000000 +0800 +++ cyrus-sasl-2.1.22-no/dlcompat-20010505/ChangeLog 1970-01-01 08:00:00.000000000 +0800 @@ -1,20 +0,0 @@ -2001-05-05 Christoph Pfisterer <cp@chrisp.de> - - * dlfcn.h: Added wrapper for C++. - -2001-01-23 Christoph Pfisterer <cp@chrisp.de> - - * dlopen.c: Added optional debugging output. Modules are now - searched for in various directories when no absolute path is - specified and the module is not found in the current directory. A - new function, _dl_search_paths, was added to accomplish the - search. Added an include for <limits.h>, because PATH_MAX is - defined there. - * Makefile: Some rearragements for the optional debugging - output. (Use "make DEBUG=1" to enable it.) - -2001-01-16 Christoph Pfisterer <cp@chrisp.de> - - * dlopen.c: Removed #include for ofi.h - it doesn't seem to be - needed. - diff -urN cyrus-sasl-2.1.22/dlcompat-20010505/dlfcn.h cyrus-sasl-2.1.22-no/dlcompat-20010505/dlfcn.h --- cyrus-sasl-2.1.22/dlcompat-20010505/dlfcn.h 2001-08-04 06:09:32.000000000 +0800 +++ cyrus-sasl-2.1.22-no/dlcompat-20010505/dlfcn.h 1970-01-01 08:00:00.000000000 +0800 @@ -1,57 +0,0 @@ -/* - * This file was modified by Christoph Pfisterer <cp@chrisp.de> - * on Sat, May 5 2001. See the file "ChangeLog" for details of what - * was changed. - * - * - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#ifdef __cplusplus -extern "C" { -#endif - -extern void * dlopen( - const char *path, - int mode); -extern void * dlsym( - void * handle, - const char *symbol); -extern const char * dlerror( - void); -extern int dlclose( - void * handle); - -#define RTLD_LAZY 0x1 -#define RTLD_NOW 0x2 -#define RTLD_LOCAL 0x4 -#define RTLD_GLOBAL 0x8 -#define RTLD_NOLOAD 0x10 -#define RTLD_SHARED 0x20 /* not used, the default */ -#define RTLD_UNSHARED 0x40 -#define RTLD_NODELETE 0x80 -#define RTLD_LAZY_UNDEF 0x100 - -#ifdef __cplusplus -} -#endif diff -urN cyrus-sasl-2.1.22/dlcompat-20010505/dlopen.c cyrus-sasl-2.1.22-no/dlcompat-20010505/dlopen.c --- cyrus-sasl-2.1.22/dlcompat-20010505/dlopen.c 2003-06-12 08:32:47.000000000 +0800 +++ cyrus-sasl-2.1.22-no/dlcompat-20010505/dlopen.c 1970-01-01 08:00:00.000000000 +0800 @@ -1,516 +0,0 @@ -/* - * This file was modified by Christoph Pfisterer <cp@chrisp.de> - * on Tue, Jan 23 2001. See the file "ChangeLog" for details of what - * was changed. - * - * - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <limits.h> -#include "mach-o/dyld.h" -#include "dlfcn.h" - -/* - * debugging macros - */ -#if DEBUG > 0 -#define DEBUG_PRINT(format) fprintf(stderr,(format));fflush(stderr) -#define DEBUG_PRINT1(format,arg1) fprintf(stderr,(format),(arg1));\ - fflush(stderr) -#define DEBUG_PRINT2(format,arg1,arg2) fprintf(stderr,(format),\ - (arg1),(arg2));fflush(stderr) -#define DEBUG_PRINT3(format,arg1,arg2,arg3) fprintf(stderr,(format),\ - (arg1),(arg2),(arg3));fflush(stderr) -#else -#define DEBUG_PRINT(format) /**/ -#define DEBUG_PRINT1(format,arg1) /**/ -#define DEBUG_PRINT2(format,arg1,arg2) /**/ -#define DEBUG_PRINT3(format,arg1,arg2,arg3) /**/ -#undef DEBUG -#endif - -/* - * The structure of a dlopen() handle. - */ -struct dlopen_handle { - dev_t dev; /* the path's device and inode number from stat(2) */ - ino_t ino; - int dlopen_mode; /* current dlopen mode for this handle */ - int dlopen_count; /* number of times dlopen() called on this handle */ - NSModule module; /* the NSModule returned by NSLinkModule() */ - struct dlopen_handle *prev; - struct dlopen_handle *next; -}; -static struct dlopen_handle *dlopen_handles = NULL; -static const struct dlopen_handle main_program_handle = {NULL}; -static char *dlerror_pointer = NULL; - -/* - * NSMakePrivateModulePublic() is not part of the public dyld API so we define - * it here. The internal dyld function pointer for - * __dyld_NSMakePrivateModulePublic is returned so thats all that maters to get - * the functionality need to implement the dlopen() interfaces. - */ -static -int -NSMakePrivateModulePublic( -NSModule module) -{ - static int (*p)(NSModule module) = NULL; - - if(p == NULL) - _dyld_func_lookup("__dyld_NSMakePrivateModulePublic", - (unsigned long *)&p); - if(p == NULL){ -#ifdef DEBUG - printf("_dyld_func_lookup of __dyld_NSMakePrivateModulePublic " - "failed\n"); -#endif - return(FALSE); - } - return(p(module)); -} - -/* - * helper routine: search for a named module in various locations - */ -static -int -_dl_search_paths( -const char *filename, -char *pathbuf, -struct stat *stat_buf) -{ - const char *pathspec; - const char *element; - const char *p; - char *q; - char *pathbuf_end; - const char *envvars[] = { - "$DYLD_LIBRARY_PATH", - "$LD_LIBRARY_PATH", - "/usr/lib:/lib", - NULL }; - int envvar_index; - - pathbuf_end = pathbuf + PATH_MAX - 8; - - for(envvar_index = 0; envvars[envvar_index]; envvar_index++){ - if(envvars[envvar_index][0] == '$'){ - pathspec = getenv(envvars[envvar_index]+1); - } - else { - pathspec = envvars[envvar_index]; - } - - if(pathspec != NULL){ - element = pathspec; - while(*element){ - /* extract path list element */ - p = element; - q = pathbuf; - while(*p && *p != ':' && q < pathbuf_end) - *q++ = *p++; - if(q == pathbuf){ /* empty element */ - if(*p){ - element = p+1; - continue; - } - break; - } - if (*p){ - element = p+1; - } - else{ - element = p; /* this terminates the loop */ - } - - /* add slash if neccessary */ - if(*(q-1) != '/' && q < pathbuf_end){ - *q++ = '/'; - } - - /* append module name */ - p = filename; - while(*p && q < pathbuf_end) *q++ = *p++; - *q++ = 0; - - if(q >= pathbuf_end){ - /* maybe add an error message here */ - break; - } - - if(stat(pathbuf, stat_buf) == 0){ - return 0; - } - } - } - } - - /* we have searched everywhere, now we give up */ - return -1; -} - -/* - * dlopen() the MacOS X version of the FreeBSD dlopen() interface. - */ -void * -dlopen( -const char *path, -int mode) -{ - const char *module_path; - void *retval; - struct stat stat_buf; - NSObjectFileImage objectFileImage; - NSObjectFileImageReturnCode ofile_result_code; - NSModule module; - struct dlopen_handle *p; - unsigned long options; - NSSymbol NSSymbol; - void (*init)(void); - char pathbuf[PATH_MAX]; - - DEBUG_PRINT2("libdl: dlopen(%s,0x%x) -> ", path, (unsigned int)mode); - - dlerror_pointer = NULL; - /* - * A NULL path is to indicate the caller wants a handle for the - * main program. - */ - if(path == NULL){ - retval = (void *)&main_program_handle; - DEBUG_PRINT1("main / %p\n", retval); - return(retval); - } - - /* see if the path exists and if so get the device and inode number */ - if(stat(path, &stat_buf) == -1){ - dlerror_pointer = strerror(errno); - - if(path[0] == '/'){ - DEBUG_PRINT1("ERROR (stat): %s\n", dlerror_pointer); - return(NULL); - } - - /* search for the module in various places */ - if(_dl_search_paths(path, pathbuf, &stat_buf)){ - /* dlerror_pointer is unmodified */ - DEBUG_PRINT1("ERROR (stat): %s\n", dlerror_pointer); - return(NULL); - } - DEBUG_PRINT1("found %s -> ", pathbuf); - module_path = pathbuf; - dlerror_pointer = NULL; - } - else{ - module_path = path; - } - - /* - * If we don't want an unshared handle see if we already have a handle - * for this path. - */ - if((mode & RTLD_UNSHARED) != RTLD_UNSHARED){ - p = dlopen_handles; - while(p != NULL){ - if(p->dev == stat_buf.st_dev && p->ino == stat_buf.st_ino){ - /* skip unshared handles */ - if((p->dlopen_mode & RTLD_UNSHARED) == RTLD_UNSHARED) - continue; - /* - * We have already created a handle for this path. The - * caller might be trying to promote an RTLD_LOCAL handle - * to a RTLD_GLOBAL. Or just looking it up with - * RTLD_NOLOAD. - */ - if((p->dlopen_mode & RTLD_LOCAL) == RTLD_LOCAL && - (mode & RTLD_GLOBAL) == RTLD_GLOBAL){ - /* promote the handle */ - if(NSMakePrivateModulePublic(p->module) == TRUE){ - p->dlopen_mode &= ~RTLD_LOCAL; - p->dlopen_mode |= RTLD_GLOBAL; - p->dlopen_count++; - DEBUG_PRINT1("%p\n", p); - return(p); - } - else{ - dlerror_pointer = "can't promote handle from " - "RTLD_LOCAL to RTLD_GLOBAL"; - DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer); - return(NULL); - } - } - p->dlopen_count++; - DEBUG_PRINT1("%p\n", p); - return(p); - } - p = p->next; - } - } - - /* - * We do not have a handle for this path if we were just trying to - * look it up return NULL to indicate we don't have it. - */ - if((mode & RTLD_NOLOAD) == RTLD_NOLOAD){ - dlerror_pointer = "no existing handle for path RTLD_NOLOAD test"; - DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer); - return(NULL); - } - - /* try to create an object file image from this path */ - ofile_result_code = NSCreateObjectFileImageFromFile(module_path, - &objectFileImage); - if(ofile_result_code != NSObjectFileImageSuccess){ - switch(ofile_result_code){ - case NSObjectFileImageFailure: - dlerror_pointer = "object file setup failure"; - DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer); - return(NULL); - case NSObjectFileImageInappropriateFile: - dlerror_pointer = "not a Mach-O MH_BUNDLE file type"; - DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer); - return(NULL); - case NSObjectFileImageArch: - dlerror_pointer = "no object for this architecture"; - DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer); - return(NULL); - case NSObjectFileImageFormat: - dlerror_pointer = "bad object file format"; - DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer); - return(NULL); - case NSObjectFileImageAccess: - dlerror_pointer = "can't read object file"; - DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer); - return(NULL); - default: - dlerror_pointer = "unknown error from " - "NSCreateObjectFileImageFromFile()"; - DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer); - return(NULL); - } - } - - /* try to link in this object file image */ - options = NSLINKMODULE_OPTION_PRIVATE; - if((mode & RTLD_NOW) == RTLD_NOW) - options |= NSLINKMODULE_OPTION_BINDNOW; - module = NSLinkModule(objectFileImage, module_path, options); - NSDestroyObjectFileImage(objectFileImage) ; - if(module == NULL){ - dlerror_pointer = "NSLinkModule() failed for dlopen()"; - DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer); - return(NULL); - } - - /* - * If the handle is to be global promote the handle. It is done this - * way to avoid multiply defined symbols. - */ - if((mode & RTLD_GLOBAL) == RTLD_GLOBAL){ - if(NSMakePrivateModulePublic(module) == FALSE){ - dlerror_pointer = "can't promote handle from RTLD_LOCAL to " - "RTLD_GLOBAL"; - DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer); - return(NULL); - } - } - - p = malloc(sizeof(struct dlopen_handle)); - if(p == NULL){ - dlerror_pointer = "can't allocate memory for the dlopen handle"; - DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer); - return(NULL); - } - - /* fill in the handle */ - p->dev = stat_buf.st_dev; - p->ino = stat_buf.st_ino; - if(mode & RTLD_GLOBAL) - p->dlopen_mode = RTLD_GLOBAL; - else - p->dlopen_mode = RTLD_LOCAL; - p->dlopen_mode |= (mode & RTLD_UNSHARED) | - (mode & RTLD_NODELETE) | - (mode & RTLD_LAZY_UNDEF); - p->dlopen_count = 1; - p->module = module; - p->prev = NULL; - p->next = dlopen_handles; - if(dlopen_handles != NULL) - dlopen_handles->prev = p; - dlopen_handles = p; - - /* call the init function if one exists */ - NSSymbol = NSLookupSymbolInModule(p->module, "__init"); - if(NSSymbol != NULL){ - init = NSAddressOfSymbol(NSSymbol); - init(); - } - - DEBUG_PRINT1("%p\n", p); - return(p); -} - -/* - * dlsym() the MacOS X version of the FreeBSD dlopen() interface. - */ -void * -dlsym( -void * handle, -const char *symbol) -{ - struct dlopen_handle *dlopen_handle, *p; - NSSymbol NSSymbol; - void *address; - - DEBUG_PRINT2("libdl: dlsym(%p,%s) -> ", handle, symbol); - - dlopen_handle = (struct dlopen_handle *)handle; - - /* - * If this is the handle for the main program do a global lookup. - */ - if(dlopen_handle == (struct dlopen_handle *)&main_program_handle){ - if(NSIsSymbolNameDefined(symbol) == TRUE){ - NSSymbol = NSLookupAndBindSymbol(symbol); - address = NSAddressOfSymbol(NSSymbol); - dlerror_pointer = NULL; - DEBUG_PRINT1("%p\n", address); - return(address); - } - else{ - dlerror_pointer = "symbol not found"; - DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer); - return(NULL); - } - } - - /* - * Find this handle and do a lookup in just this module. - */ - p = dlopen_handles; - while(p != NULL){ - if(dlopen_handle == p){ - NSSymbol = NSLookupSymbolInModule(p->module, symbol); - if(NSSymbol != NULL){ - address = NSAddressOfSymbol(NSSymbol); - dlerror_pointer = NULL; - DEBUG_PRINT1("%p\n", address); - return(address); - } - else{ - dlerror_pointer = "symbol not found"; - DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer); - return(NULL); - } - } - p = p->next; - } - - dlerror_pointer = "bad handle passed to dlsym()"; - DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer); - return(NULL); -} - -/* - * dlerror() the MacOS X version of the FreeBSD dlopen() interface. - */ -const char * -dlerror( -void) -{ - const char *p; - - p = (const char *)dlerror_pointer; - dlerror_pointer = NULL; - return(p); -} - -/* - * dlclose() the MacOS X version of the FreeBSD dlopen() interface. - */ -int -dlclose( -void * handle) -{ - struct dlopen_handle *p, *q; - unsigned long options; - NSSymbol NSSymbol; - void (*fini)(void); - - DEBUG_PRINT1("libdl: dlclose(%p) -> ", handle); - - dlerror_pointer = NULL; - q = (struct dlopen_handle *)handle; - p = dlopen_handles; - while(p != NULL){ - if(p == q){ - /* if the dlopen() count is not zero we are done */ - p->dlopen_count--; - if(p->dlopen_count != 0){ - DEBUG_PRINT("OK"); - return(0); - } - - /* call the fini function if one exists */ - NSSymbol = NSLookupSymbolInModule(p->module, "__fini"); - if(NSSymbol != NULL){ - fini = NSAddressOfSymbol(NSSymbol); - fini(); - } - - /* unlink the module for this handle */ - options = 0; - if(p->dlopen_mode & RTLD_NODELETE) - options |= NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED; - if(p->dlopen_mode & RTLD_LAZY_UNDEF) - options |= NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES; - if(NSUnLinkModule(p->module, options) == FALSE){ - dlerror_pointer = "NSUnLinkModule() failed for dlclose()"; - DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer); - return(-1); - } - if(p->prev != NULL) - p->prev->next = p->next; - if(p->next != NULL) - p->next->prev = p->prev; - if(dlopen_handles == p) - dlopen_handles = p->next; - free(p); - DEBUG_PRINT("OK"); - return(0); - } - p = p->next; - } - dlerror_pointer = "invalid handle passed to dlclose()"; - DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer); - return(-1); -} diff -urN cyrus-sasl-2.1.22/dlcompat-20010505/Makefile cyrus-sasl-2.1.22-no/dlcompat-20010505/Makefile --- cyrus-sasl-2.1.22/dlcompat-20010505/Makefile 2002-05-29 08:08:35.000000000 +0800 +++ cyrus-sasl-2.1.22-no/dlcompat-20010505/Makefile 1970-01-01 08:00:00.000000000 +0800 @@ -1,63 +0,0 @@ -# -# Makefile for dlcompat -# -# -# Copyright (c) 2001 Christoph Pfisterer. -# -# Portions Copyright (c) 1999-2001 Apple Computer, Inc. All Rights -# Reserved. -# -# This file contains Original Code and/or Modifications of Original -# Code as defined in and that are subject to the Apple Public Source -# License Version 1.2 (the "License"). You may not use this file -# except in compliance with the License. Please obtain a copy of the -# License at http://www.apple.com/publicsource and read it before -# using this file. -# -# The Original Code and all software distributed under the License are -# distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER -# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, -# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR -# NON-INFRINGEMENT. Please see the License for the specific language -# governing rights and limitations under the License. -# - - -prefix=/usr/local -DEBUG=0 - -CC=cc -CFLAGS=-Wall -O2 -DDEBUG=$(DEBUG) -AR=ar cru -RANLIB=ranlib -INSTALL=install - -OBJS = dlopen.o - - -all: libdl.a libdl.dylib - -install: all - if test ! -d $(prefix)/lib ; then mkdir $(prefix)/lib ; fi - $(INSTALL) -m 644 libdl.a $(prefix)/lib - $(RANLIB) $(prefix)/lib/libdl.a - chmod 644 $(prefix)/lib/libdl.a - $(INSTALL) -m 755 libdl.dylib $(prefix)/lib - if test ! -d $(prefix)/include ; then mkdir $(prefix)/include ; fi - $(INSTALL) -c -m 644 dlfcn.h $(prefix)/include - -.c.o: - $(CC) $(CFLAGS) -fno-common -o $@ -c $< - -libdl.a: $(OBJS) - $(AR) libdl.a $(OBJS) - $(RANLIB) libdl.a - -libdl.dylib: $(OBJS) - $(CC) -dynamiclib -undefined error -o libdl.dylib $(OBJS) -install_name $(prefix)/lib/libdl.dylib - -clean: - rm -f $(OBJS) libdl.* - -# EOF diff -urN cyrus-sasl-2.1.22/dlcompat-20010505/README cyrus-sasl-2.1.22-no/dlcompat-20010505/README --- cyrus-sasl-2.1.22/dlcompat-20010505/README 2001-08-04 06:09:32.000000000 +0800 +++ cyrus-sasl-2.1.22-no/dlcompat-20010505/README 1970-01-01 08:00:00.000000000 +0800 @@ -1,71 +0,0 @@ - dlcompat for Darwin -===================== - -This is release 20010505 of dlcompat. dlcompat is a small library that -emulates the dlopen() interface on top of Darwin's dyld API. It is -based on a CVS snapshot of Apple's Darwin CVS repository, taken on -Jan 16 2001 (and still current as of May 5 2001). Since it's based on -Apple code, it is released under the terms of the Apple Public Source -License; see the file APPLE_LICENSE for the text of the license. - -Changes were made to automatically search for the module in several -directories (taken from the environment variables DYLD_LIBRARY_PATH -and LD_LIBRARY_PATH, plus /usr/lib and /lib) when no absolute path is -specified and the module is not found in the current directory. If you -prefer to run unmodified Apple code, download release 20010116. - - - Installation --------------- -As root, type: - - make install - -This will compile the source file, generate both a static and shared -library called libdl and install it into /usr/local/lib. The header -file dlfcn.h will be installed in /usr/local/include. - -If you want to place the files somewhere else, run - - make clean - make install prefix=<prefix> - -where <prefix> is the hierarchy you want to install into, e.g. /usr -for /usr/lib and /usr/include (_NOT_ recommended!). - -To enable debugging output, run - - make clean - make DEBUG=1 - make install - -Combinations of those commands are left as an excercise to the -reader. :-) - - - Usage -------- -Software that uses GNU autoconf will likely check for a library called -libdl, that's why I named it that way. For software that doesn't find -the library on its own, you must add a '-ldl' to the appropriate -Makefile (or environment) variable, usually LIBS. - -If you installed dlcompat into a directory other than /usr/local/lib, -you must tell the compiler where to find it. Add '-L<prefix>/lib' to -LDFLAGS (or CFLAGS) and '-I<prefix>/include' to CPPFLAGS (or CFLAGS). - - - Genesis ---------- -The files dlfcn.h and dlopen.c are taken from the Darwin CVS, -directory Commands/Apple/cctools/libdyld. For release 20010116, I -removed an unneccessary include statement from dlopen.c and added the -Makefile. For release 20010123, I added debugging output and library -searching. The changes are clearly documented, as required by the -Apple Public Source License. For release 20010505, I added wrappers to -disable C++ name mangling. That allows the library to be used by C++ -code, but be aware that there are issues with C++ and bundles, like -static initializers not being called. - - -Christoph Pfisterer <cp@chrisp.de> diff -urN cyrus-sasl-2.1.22/plugins/srp.c cyrus-sasl-2.1.22-no/plugins/srp.c --- cyrus-sasl-2.1.22/plugins/srp.c 2006-05-18 00:46:17.000000000 +0800 +++ cyrus-sasl-2.1.22-no/plugins/srp.c 1970-01-01 08:00:00.000000000 +0800 @@ -1,3179 +0,0 @@ -/* SRP SASL plugin - * Ken Murchison - * Tim Martin 3/17/00 - * $Id: srp.c,v 1.58 2006/04/24 19:21:44 mel Exp $ - */ -/* - * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name "Carnegie Mellon University" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For permission or any other legal - * details, please contact - * Office of Technology Transfer - * Carnegie Mellon University - * 5000 Forbes Avenue - * Pittsburgh, PA 15213-3890 - * (412) 268-4387, fax: (412) 268-7395 - * tech-transfer@andrew.cmu.edu - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Computing Services - * at Carnegie Mellon University (http://www.cmu.edu/computing/)." - * - * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE - * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * Notes: - * - * - The authentication exchanges *should* be correct (per draft -08) - * but we won't know until we do some interop testing. - * - * - The security layers don't conform to draft -08: - * o We don't use eos() and os() elements in an SRP buffer, we send - * just the bare octets. - * o We don't yet use the PRNG() and KDF() primatives described in - * section 5.1. - * - * - Are we using cIV and sIV correctly for encrypt/decrypt? - * - * - We don't implement fast reauth. - */ - -#include <config.h> -#include <assert.h> -#include <ctype.h> -#include <stdio.h> -#include <limits.h> -#include <stdarg.h> - -#ifndef UINT32_MAX -#define UINT32_MAX 4294967295U -#endif - -#if UINT_MAX == UINT32_MAX -typedef unsigned int uint32; -#elif ULONG_MAX == UINT32_MAX -typedef unsigned long uint32; -#elif USHRT_MAX == UINT32_MAX -typedef unsigned short uint32; -#else -#error dont know what to use for uint32 -#endif - -/* for big number support */ -#include <openssl/bn.h> - -/* for digest and cipher support */ -#include <openssl/evp.h> -#include <openssl/hmac.h> -#include <openssl/md5.h> - -#include <sasl.h> -#define MD5_H /* suppress internal MD5 */ -#include <saslplug.h> - -#include "plugin_common.h" - -#ifdef macintosh -#include <sasl_srp_plugin_decl.h> -#endif - -/***************************** Common Section *****************************/ - -static const char plugin_id[] = "$Id: srp.c,v 1.58 2006/04/24 19:21:44 mel Exp $"; - -/* Size limit of cipher block size */ -#define SRP_MAXBLOCKSIZE 16 -/* Size limit of SRP buffer */ -#define SRP_MAXBUFFERSIZE 2147483643 - -#define DEFAULT_MDA "SHA-1" - -#define OPTION_MDA "mda=" -#define OPTION_REPLAY_DETECTION "replay_detection" -#define OPTION_INTEGRITY "integrity=" -#define OPTION_CONFIDENTIALITY "confidentiality=" -#define OPTION_MANDATORY "mandatory=" -#define OPTION_MAXBUFFERSIZE "maxbuffersize=" - -/* Table of recommended Modulus (base 16) and Generator pairs */ -struct Ng { - char *N; - unsigned long g; -} Ng_tab[] = { - /* [264 bits] */ - { "115B8B692E0E045692CF280B436735C77A5A9E8A9E7ED56C965F87DB5B2A2ECE3", - 2 - }, - /* [384 bits] */ - { "8025363296FB943FCE54BE717E0E2958A02A9672EF561953B2BAA3BAACC3ED5754EB764C7AB7184578C57D5949CCB41B", - 2 - }, - /* [512 bits] */ - { "D4C7F8A2B32C11B8FBA9581EC4BA4F1B04215642EF7355E37C0FC0443EF756EA2C6B8EEB755A1C723027663CAA265EF785B8FF6A9B35227A52D86633DBDFCA43", - 2 - }, - /* [640 bits] */ - { "C94D67EB5B1A2346E8AB422FC6A0EDAEDA8C7F894C9EEEC42F9ED250FD7F0046E5AF2CF73D6B2FA26BB08033DA4DE322E144E7A8E9B12A0E4637F6371F34A2071C4B3836CBEEAB15034460FAA7ADF483", - 2 - }, - /* [768 bits] */ - { "B344C7C4F8C495031BB4E04FF8F84EE95008163940B9558276744D91F7CC9F402653BE7147F00F576B93754BCDDF71B636F2099E6FFF90E79575F3D0DE694AFF737D9BE9713CEF8D837ADA6380B1093E94B6A529A8C6C2BE33E0867C60C3262B", - 2 - }, - /* [1024 bits] */ - { "EEAF0AB9ADB38DD69C33F80AFA8FC5E86072618775FF3C0B9EA2314C9C256576D674DF7496EA81D3383B4813D692C6E0E0D5D8E250B98BE48E495C1D6089DAD15DC7D7B46154D6B6CE8EF4AD69B15D4982559B297BCF1885C529F566660E57EC68EDBC3C05726CC02FD4CBF4976EAA9AFD5138FE8376435B9FC61D2FC0EB06E3", - 2 - }, - /* [1280 bits] */ - { "D77946826E811914B39401D56A0A7843A8E7575D738C672A090AB1187D690DC43872FC06A7B6A43F3B95BEAEC7DF04B9D242EBDC481111283216CE816E004B786C5FCE856780D41837D95AD787A50BBE90BD3A9C98AC0F5FC0DE744B1CDE1891690894BC1F65E00DE15B4B2AA6D87100C9ECC2527E45EB849DEB14BB2049B163EA04187FD27C1BD9C7958CD40CE7067A9C024F9B7C5A0B4F5003686161F0605B", - 2 - }, - /* [1536 bits] */ - { "9DEF3CAFB939277AB1F12A8617A47BBBDBA51DF499AC4C80BEEEA9614B19CC4D5F4F5F556E27CBDE51C6A94BE4607A291558903BA0D0F84380B655BB9A22E8DCDF028A7CEC67F0D08134B1C8B97989149B609E0BE3BAB63D47548381DBC5B1FC764E3F4B53DD9DA1158BFD3E2B9C8CF56EDF019539349627DB2FD53D24B7C48665772E437D6C7F8CE442734AF7CCB7AE837C264AE3A9BEB87F8A2FE9B8B5292E5A021FFF5E91479E8CE7A28C2442C6F315180F93499A234DCF76E3FED135F9BB", - 2 - }, - /* [2048 bits] */ - { "AC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC3192943DB56050A37329CBB4A099ED8193E0757767A13DD52312AB4B03310DCD7F48A9DA04FD50E8083969EDB767B0CF6095179A163AB3661A05FBD5FAAAE82918A9962F0B93B855F97993EC975EEAA80D740ADBF4FF747359D041D5C33EA71D281E446B14773BCA97B43A23FB801676BD207A436C6481F1D2B9078717461A5B9D32E688F87748544523B524B0D57D5EA77A2775D2ECFA032CFBDBF52FB3786160279004E57AE6AF874E7303CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DBFBB694B5C803D89F7AE435DE236D525F54759B65E372FCD68EF20FA7111F9E4AFF73", - 2 - } -}; - -#define NUM_Ng (sizeof(Ng_tab) / sizeof(struct Ng)) - - -typedef struct layer_option_s { - const char *name; /* name used in option strings */ - unsigned enabled; /* enabled? determined at run-time */ - unsigned bit; /* unique bit in bitmask */ - sasl_ssf_t ssf; /* ssf of layer */ - const char *evp_name; /* name used for lookup in EVP table */ -} layer_option_t; - -static layer_option_t digest_options[] = { - { "SHA-1", 0, (1<<0), 1, "sha1" }, - { "RIPEMD-160", 0, (1<<1), 1, "rmd160" }, - { "MD5", 0, (1<<2), 1, "md5" }, - { NULL, 0, 0, 0, NULL } -}; -static layer_option_t *default_digest = &digest_options[0]; -static layer_option_t *server_mda = NULL; - -static layer_option_t cipher_options[] = { - { "DES", 0, (1<<0), 56, "des-ofb" }, - { "3DES", 0, (1<<1), 112, "des-ede-ofb" }, - { "AES", 0, (1<<2), 128, "aes-128-ofb" }, - { "Blowfish", 0, (1<<3), 128, "bf-ofb" }, - { "CAST-128", 0, (1<<4), 128, "cast5-ofb" }, - { "IDEA", 0, (1<<5), 128, "idea-ofb" }, - { NULL, 0, 0, 0, NULL} -}; -/* XXX Hack until OpenSSL 0.9.7 */ -#if OPENSSL_VERSION_NUMBER < 0x00907000L -static layer_option_t *default_cipher = &cipher_options[0]; -#else -static layer_option_t *default_cipher = &cipher_options[2]; -#endif - - -enum { - BIT_REPLAY_DETECTION= (1<<0), - BIT_INTEGRITY= (1<<1), - BIT_CONFIDENTIALITY= (1<<2) -}; - -typedef struct srp_options_s { - unsigned mda; /* bitmask of MDAs */ - unsigned replay_detection; /* replay detection on/off flag */ - unsigned integrity; /* bitmask of integrity layers */ - unsigned confidentiality; /* bitmask of confidentiality layers */ - unsigned mandatory; /* bitmask of mandatory layers */ - unsigned long maxbufsize; /* max # bytes processed by security layer */ -} srp_options_t; - -/* The main SRP context */ -typedef struct context { - int state; - - BIGNUM N; /* safe prime modulus */ - BIGNUM g; /* generator */ - - BIGNUM v; /* password verifier */ - - BIGNUM b; /* server private key */ - BIGNUM B; /* server public key */ - - BIGNUM a; /* client private key */ - BIGNUM A; /* client public key */ - - char K[EVP_MAX_MD_SIZE]; /* shared context key */ - int Klen; - - char M1[EVP_MAX_MD_SIZE]; /* client evidence */ - int M1len; - - char *authid; /* authentication id (server) */ - char *userid; /* authorization id (server) */ - sasl_secret_t *password; /* user secret (client) */ - unsigned int free_password; /* set if we need to free password */ - - char *client_options; - char *server_options; - - srp_options_t client_opts; /* cache between client steps */ - char cIV[SRP_MAXBLOCKSIZE]; /* cache between client steps */ - - char *salt; /* password salt */ - int saltlen; - - const EVP_MD *md; /* underlying MDA */ - - /* copy of utils from the params structures */ - const sasl_utils_t *utils; - - /* per-step mem management */ - char *out_buf; - unsigned out_buf_len; - - /* Layer foo */ - unsigned layer; /* bitmask of enabled layers */ - const EVP_MD *hmac_md; /* HMAC for integrity */ - HMAC_CTX hmac_send_ctx; - HMAC_CTX hmac_recv_ctx; - - const EVP_CIPHER *cipher; /* cipher for confidentiality */ - EVP_CIPHER_CTX cipher_enc_ctx; - EVP_CIPHER_CTX cipher_dec_ctx; - - /* replay detection sequence numbers */ - int seqnum_out; - int seqnum_in; - - /* for encoding/decoding mem management */ - char *encode_buf, *decode_buf, *decode_pkt_buf; - unsigned encode_buf_len, decode_buf_len, decode_pkt_buf_len; - - /* layers buffering */ - decode_context_t decode_context; - -} context_t; - -static int srp_encode(void *context, - const struct iovec *invec, - unsigned numiov, - const char **output, - unsigned *outputlen) -{ - context_t *text = (context_t *) context; - unsigned i; - char *input; - unsigned long inputlen, tmpnum; - int ret; - - if (!context || !invec || !numiov || !output || !outputlen) { - PARAMERROR( text->utils ); - return SASL_BADPARAM; - } - - /* calculate total size of input */ - for (i = 0, inputlen = 0; i < numiov; i++) - inputlen += invec[i].iov_len; - - /* allocate a buffer for the output */ - ret = _plug_buf_alloc(text->utils, &text->encode_buf, - &text->encode_buf_len, - 4 + /* for length */ - inputlen + /* for content */ - SRP_MAXBLOCKSIZE + /* for PKCS padding */ - EVP_MAX_MD_SIZE); /* for HMAC */ - if (ret != SASL_OK) return ret; - - *outputlen = 4; /* length */ - - /* operate on each iovec */ - for (i = 0; i < numiov; i++) { - input = invec[i].iov_base; - inputlen = invec[i].iov_len; - - if (text->layer & BIT_CONFIDENTIALITY) { - unsigned enclen; - - /* encrypt the data into the output buffer */ - EVP_EncryptUpdate(&text->cipher_enc_ctx, - text->encode_buf + *outputlen, &enclen, - input, inputlen); - *outputlen += enclen; - - /* switch the input to the encrypted data */ - input = text->encode_buf + 4; - inputlen = *outputlen - 4; - } - else { - /* copy the raw input to the output */ - memcpy(text->encode_buf + *outputlen, input, inputlen); - *outputlen += inputlen; - } - } - - if (text->layer & BIT_CONFIDENTIALITY) { - unsigned enclen; - - /* encrypt the last block of data into the output buffer */ - EVP_EncryptFinal(&text->cipher_enc_ctx, - text->encode_buf + *outputlen, &enclen); - *outputlen += enclen; - } - - if (text->layer & BIT_INTEGRITY) { - unsigned hashlen; - - /* hash the content */ - HMAC_Update(&text->hmac_send_ctx, text->encode_buf+4, *outputlen-4); - - if (text->layer & BIT_REPLAY_DETECTION) { - /* hash the sequence number */ - tmpnum = htonl(text->seqnum_out); - HMAC_Update(&text->hmac_send_ctx, (char *) &tmpnum, 4); - - text->seqnum_out++; - } - - /* append the HMAC into the output buffer */ - HMAC_Final(&text->hmac_send_ctx, text->encode_buf + *outputlen, - &hashlen); - *outputlen += hashlen; - } - - /* prepend the length of the output */ - tmpnum = *outputlen - 4; - tmpnum = htonl(tmpnum); - memcpy(text->encode_buf, &tmpnum, 4); - - *output = text->encode_buf; - - return SASL_OK; -} - -/* decode a single SRP packet */ -static int srp_decode_packet(void *context, - const char *input, - unsigned inputlen, - char **output, - unsigned *outputlen) -{ - context_t *text = (context_t *) context; - int ret; - - if (text->layer & BIT_INTEGRITY) { - const char *hash; - char myhash[EVP_MAX_MD_SIZE]; - unsigned hashlen, myhashlen, i; - unsigned long tmpnum; - - hashlen = EVP_MD_size(text->hmac_md); - - if (inputlen < hashlen) { - text->utils->seterror(text->utils->conn, 0, - "SRP input is smaller " - "than hash length: %d vs %d\n", - inputlen, hashlen); - return SASL_BADPROT; - } - - inputlen -= hashlen; - hash = input + inputlen; - - /* create our own hash from the input */ - HMAC_Update(&text->hmac_recv_ctx, input, inputlen); - - if (text->layer & BIT_REPLAY_DETECTION) { - /* hash the sequence number */ - tmpnum = htonl(text->seqnum_in); - HMAC_Update(&text->hmac_recv_ctx, (char *) &tmpnum, 4); - - text->seqnum_in++; - } - - HMAC_Final(&text->hmac_recv_ctx, myhash, &myhashlen); - - /* compare hashes */ - for (i = 0; i < hashlen; i++) { - if ((myhashlen != hashlen) || (myhash[i] != hash[i])) { - SETERROR(text->utils, "Hash is incorrect\n"); - return SASL_BADMAC; - } - } - } - - ret = _plug_buf_alloc(text->utils, &(text->decode_pkt_buf), - &(text->decode_pkt_buf_len), - inputlen); - if (ret != SASL_OK) return ret; - - if (text->layer & BIT_CONFIDENTIALITY) { - unsigned declen; - - /* decrypt the data into the output buffer */ - EVP_DecryptUpdate(&text->cipher_dec_ctx, - text->decode_pkt_buf, &declen, - (char *) input, inputlen); - *outputlen = declen; - - EVP_DecryptFinal(&text->cipher_dec_ctx, - text->decode_pkt_buf + declen, &declen); - *outputlen += declen; - } else { - /* copy the raw input to the output */ - memcpy(text->decode_pkt_buf, input, inputlen); - *outputlen = inputlen; - } - - *output = text->decode_pkt_buf; - - return SASL_OK; -} - -/* decode and concatenate multiple SRP packets */ -static int srp_decode(void *context, - const char *input, unsigned inputlen, - const char **output, unsigned *outputlen) -{ - context_t *text = (context_t *) context; - int ret; - - ret = _plug_decode(&text->decode_context, input, inputlen, - &text->decode_buf, &text->decode_buf_len, outputlen, - srp_decode_packet, text); - - *output = text->decode_buf; - - return ret; -} - -/* - * Convert a big integer to it's byte representation - */ -static int BigIntToBytes(BIGNUM *num, char *out, int maxoutlen, int *outlen) -{ - int len; - - len = BN_num_bytes(num); - - if (len > maxoutlen) return SASL_FAIL; - - *outlen = BN_bn2bin(num, out); - - return SASL_OK; -} - -/* - * Compare a big integer against a word. - */ -static int BigIntCmpWord(BIGNUM *a, BN_ULONG w) -{ - BIGNUM *b = BN_new(); - int r; - - BN_set_word(b, w); - r = BN_cmp(a, b); - BN_free(b); - return r; -} - -/* - * Generate a random big integer. - */ -static void GetRandBigInt(BIGNUM *out) -{ - BN_init(out); - - /* xxx likely should use sasl random funcs */ - BN_rand(out, SRP_MAXBLOCKSIZE*8, 0, 0); -} - -#define MAX_BUFFER_LEN 2147483643 -#define MAX_MPI_LEN 65535 -#define MAX_UTF8_LEN 65535 -#define MAX_OS_LEN 255 - -/* - * Make an SRP buffer from the data specified by the fmt string. - */ -static int MakeBuffer(const sasl_utils_t *utils, char **buf, unsigned *buflen, - unsigned *outlen, const char *fmt, ...) -{ - va_list ap; - char *p, *out = NULL; - int r, alloclen, len; - BIGNUM *mpi; - char *os, *str, c; - uint32 u; - short ns; - long totlen; - - /* first pass to calculate size of buffer */ - va_start(ap, fmt); - for (p = (char *) fmt, alloclen = 0; *p; p++) { - if (*p != '%') { - alloclen++; - continue; - } - - switch (*++p) { - case 'm': - /* MPI */ - mpi = va_arg(ap, BIGNUM *); - len = BN_num_bytes(mpi); - if (len > MAX_MPI_LEN) { - utils->log(NULL, SASL_LOG_ERR, - "String too long to create mpi string\n"); - r = SASL_FAIL; - goto done; - } - alloclen += len + 2; - break; - - case 'o': - /* octet sequence (len followed by data) */ - len = va_arg(ap, int); - if (len > MAX_OS_LEN) { - utils->log(NULL, SASL_LOG_ERR, - "String too long to create os string\n"); - r = SASL_FAIL; - goto done; - } - alloclen += len + 1; - os = va_arg(ap, char *); - break; - - case 's': - /* string */ - str = va_arg(ap, char *); - len = strlen(str); - if (len > MAX_UTF8_LEN) { - utils->log(NULL, SASL_LOG_ERR, - "String too long to create utf8 string\n"); - r = SASL_FAIL; - goto done; - } - alloclen += len + 2; - break; - - case 'u': - /* unsigned int */ - u = va_arg(ap, uint32); - alloclen += sizeof(uint32); - break; - - case 'c': - /* char */ - c = va_arg(ap, int) & 0xFF; - alloclen += 1; - break; - - default: - alloclen += 1; - break; - } - } - va_end(ap); - - if (alloclen > MAX_BUFFER_LEN) { - utils->log(NULL, SASL_LOG_ERR, - "String too long to create SRP buffer string\n"); - return SASL_FAIL; - } - - alloclen += 4; - r = _plug_buf_alloc(utils, buf, buflen, alloclen); - if (r != SASL_OK) return r; - - out = *buf + 4; /* skip size for now */ - - /* second pass to fill buffer */ - va_start(ap, fmt); - for (p = (char *) fmt; *p; p++) { - if (*p != '%') { - *out = *p; - out++; - continue; - } - - switch (*++p) { - case 'm': - /* MPI */ - mpi = va_arg(ap, BIGNUM *); - r = BigIntToBytes(mpi, out+2, BN_num_bytes(mpi), &len); - if (r) goto done; - ns = htons(len); - memcpy(out, &ns, 2); /* add 2 byte len (network order) */ - out += len + 2; - break; - - case 'o': - /* octet sequence (len followed by data) */ - len = va_arg(ap, int); - os = va_arg(ap, char *); - *out = len & 0xFF; /* add 1 byte len */ - memcpy(out+1, os, len); /* add data */ - out += len+1; - break; - - case 's': - /* string */ - str = va_arg(ap, char *); - /* xxx do actual utf8 conversion */ - len = strlen(str); - ns = htons(len); - memcpy(out, &ns, 2); /* add 2 byte len (network order) */ - memcpy(out+2, str, len); /* add string */ - out += len + 2; - break; - - case 'u': - /* unsigned int */ - u = va_arg(ap, uint32); - u = htonl(u); - memcpy(out, &u, sizeof(uint32)); - out += sizeof(uint32); - break; - - case 'c': - /* char */ - c = va_arg(ap, int) & 0xFF; - *out = c; - out++; - break; - - default: - *out = *p; - out++; - break; - } - } - done: - va_end(ap); - - *outlen = out - *buf; - - /* add 4 byte len (network order) */ - totlen = htonl(*outlen - 4); - memcpy(*buf, &totlen, 4); - - return r; -} - -/* - * Extract an SRP buffer into the data specified by the fmt string. - * - * A '-' flag means don't allocate memory for the data ('o' only). - */ -static int UnBuffer(const sasl_utils_t *utils, const char *buf, - unsigned buflen, const char *fmt, ...) -{ - va_list ap; - char *p; - int r = SASL_OK, noalloc; - BIGNUM *mpi; - char **os, **str; - uint32 *u; - unsigned short ns; - unsigned len; - - if (!buf || buflen < 4) { - utils->seterror(utils->conn, 0, - "Buffer is not big enough to be SRP buffer: %d\n", - buflen); - return SASL_BADPROT; - } - - /* get the length */ - memcpy(&len, buf, 4); - len = ntohl(len); - buf += 4; - buflen -= 4; - - /* make sure it's right */ - if (len != buflen) { - SETERROR(utils, "SRP Buffer isn't of the right length\n"); - return SASL_BADPROT; - } - - va_start(ap, fmt); - for (p = (char *) fmt; *p; p++) { - if (*p != '%') { - if (*buf != *p) { - r = SASL_BADPROT; - goto done; - } - buf++; - buflen--; - continue; - } - - /* check for noalloc flag */ - if ((noalloc = (*++p == '-'))) ++p; - - switch (*p) { - case 'm': - /* MPI */ - if (buflen < 2) { - SETERROR(utils, "Buffer is not big enough to be SRP MPI\n"); - r = SASL_BADPROT; - goto done; - } - - /* get the length */ - memcpy(&ns, buf, 2); - len = ntohs(ns); - buf += 2; - buflen -= 2; - - /* make sure it's right */ - if (len > buflen) { - SETERROR(utils, "Not enough data for this SRP MPI\n"); - r = SASL_BADPROT; - goto done; - } - - mpi = va_arg(ap, BIGNUM *); - BN_init(mpi); - BN_bin2bn(buf, len, mpi); - break; - - case 'o': - /* octet sequence (len followed by data) */ - if (buflen < 1) { - SETERROR(utils, "Buffer is not big enough to be SRP os\n"); - r = SASL_BADPROT; - goto done; - } - - /* get the length */ - len = (unsigned char) *buf; - buf++; - buflen--; - - /* make sure it's right */ - if (len > buflen) { - SETERROR(utils, "Not enough data for this SRP os\n"); - r = SASL_BADPROT; - goto done; - } - - *(va_arg(ap, int *)) = len; - os = va_arg(ap, char **); - - if (noalloc) - *os = (char *) buf; - else { - *os = (char *) utils->malloc(len); - if (!*os) { - r = SASL_NOMEM; - goto done; - } - - memcpy(*os, buf, len); - } - break; - - case 's': - /* string */ - if (buflen < 2) { - SETERROR(utils, "Buffer is not big enough to be SRP UTF8\n"); - r = SASL_BADPROT; - goto done; - } - - /* get the length */ - memcpy(&ns, buf, 2); - len = ntohs(ns); - buf += 2; - buflen -= 2; - - /* make sure it's right */ - if (len > buflen) { - SETERROR(utils, "Not enough data for this SRP UTF8\n"); - r = SASL_BADPROT; - goto done; - } - - str = va_arg(ap, char **); - *str = (char *) utils->malloc(len+1); /* +1 for NUL */ - if (!*str) { - r = SASL_NOMEM; - goto done; - } - - memcpy(*str, buf, len); - (*str)[len] = '\0'; - break; - - case 'u': - /* unsigned int */ - if (buflen < sizeof(uint32)) { - SETERROR(utils, "Buffer is not big enough to be SRP uint\n"); - r = SASL_BADPROT; - goto done; - } - - len = sizeof(uint32); - u = va_arg(ap, uint32*); - memcpy(u, buf, len); - *u = ntohs(*u); - break; - - case 'c': - /* char */ - if (buflen < 1) { - SETERROR(utils, "Buffer is not big enough to be SRP char\n"); - r = SASL_BADPROT; - goto done; - } - - len = 1; - *(va_arg(ap, char *)) = *buf; - break; - - default: - len = 1; - if (*buf != *p) { - r = SASL_BADPROT; - goto done; - } - break; - } - - buf += len; - buflen -= len; - } - - done: - va_end(ap); - - if (buflen != 0) { - SETERROR(utils, "Extra data in SRP buffer\n"); - r = SASL_BADPROT; - } - - return r; -} - -/* - * Apply the hash function to the data specifed by the fmt string. - */ -static int MakeHash(const EVP_MD *md, unsigned char hash[], int *hashlen, - const char *fmt, ...) -{ - va_list ap; - char *p, buf[4096], *in; - int inlen; - EVP_MD_CTX mdctx; - int r = 0, hflag; - - EVP_DigestInit(&mdctx, md); - - va_start(ap, fmt); - for (p = (char *) fmt; *p; p++) { - if (*p != '%') { - in = p; - inlen = 1; - hflag = 0; - } - else { - if ((hflag = (*++p == 'h'))) ++p; - - switch (*p) { - case 'm': { - /* MPI */ - BIGNUM *mval = va_arg(ap, BIGNUM *); - - in = buf; - r = BigIntToBytes(mval, buf, sizeof(buf)-1, &inlen); - if (r) goto done; - break; - } - - case 'o': { - /* octet sequence (len followed by data) */ - inlen = va_arg(ap, int); - in = va_arg(ap, char *); - break; - } - - case 's': - /* string */ - in = va_arg(ap, char *); - inlen = strlen(in); - break; - - case 'u': { - /* unsigned int */ - uint32 uval = va_arg(ap, uint32); - - in = buf; - inlen = sizeof(uint32); - *((uint32 *) buf) = htonl(uval); - break; - } - - default: - in = p; - inlen = 1; - break; - } - } - - if (hflag) { - /* hash data separately before adding to current hash */ - EVP_MD_CTX tmpctx; - - EVP_DigestInit(&tmpctx, md); - EVP_DigestUpdate(&tmpctx, in, inlen); - EVP_DigestFinal(&tmpctx, buf, &inlen); - in = buf; - } - - EVP_DigestUpdate(&mdctx, in, inlen); - } - done: - va_end(ap); - - EVP_DigestFinal(&mdctx, hash, hashlen); - - return r; -} - -static int CalculateX(context_t *text, const char *salt, int saltlen, - const char *user, const char *pass, int passlen, - BIGNUM *x) -{ - char hash[EVP_MAX_MD_SIZE]; - int hashlen; - - /* x = H(salt | H(user | ':' | pass)) */ - MakeHash(text->md, hash, &hashlen, "%s:%o", user, passlen, pass); - MakeHash(text->md, hash, &hashlen, "%o%o", saltlen, salt, hashlen, hash); - - BN_init(x); - BN_bin2bn(hash, hashlen, x); - - return SASL_OK; -} - -static int CalculateM1(context_t *text, BIGNUM *N, BIGNUM *g, - char *U, char *salt, int saltlen, - BIGNUM *A, BIGNUM *B, char *K, int Klen, - char *I, char *L, char *M1, int *M1len) -{ - int r, i, len; - unsigned char Nhash[EVP_MAX_MD_SIZE]; - unsigned char ghash[EVP_MAX_MD_SIZE]; - unsigned char Ng[EVP_MAX_MD_SIZE]; - - /* bytes(H( bytes(N) )) ^ bytes( H( bytes(g) )) - ^ is the bitwise XOR operator. */ - r = MakeHash(text->md, Nhash, &len, "%m", N); - if (r) return r; - r = MakeHash(text->md, ghash, &len, "%m", g); - if (r) return r; - - for (i = 0; i < len; i++) { - Ng[i] = (Nhash[i] ^ ghash[i]); - } - - r = MakeHash(text->md, M1, M1len, "%o%hs%o%m%m%o%hs%hs", - len, Ng, U, saltlen, salt, A, B, Klen, K, I, L); - - return r; -} - -static int CalculateM2(context_t *text, BIGNUM *A, - char *M1, int M1len, char *K, int Klen, - char *I, char *o, char *sid, uint32 ttl, - char *M2, int *M2len) -{ - int r; - - r = MakeHash(text->md, M2, M2len, "%m%o%o%hs%hs%s%u", - A, M1len, M1, Klen, K, I, o, sid, ttl); - - return r; -} - -/* Parse an option out of an option string - * Place found option in 'option' - * 'nextptr' points to rest of string or NULL if at end - */ -static int ParseOption(const sasl_utils_t *utils, - char *in, char **option, char **nextptr) -{ - char *comma; - int len; - int i; - - if (strlen(in) == 0) { - *option = NULL; - return SASL_OK; - } - - comma = strchr(in,','); - if (comma == NULL) comma = in + strlen(in); - - len = comma - in; - - *option = utils->malloc(len + 1); - if (!*option) return SASL_NOMEM; - - /* lowercase string */ - for (i = 0; i < len; i++) { - (*option)[i] = tolower((int)in[i]); - } - (*option)[len] = '\0'; - - if (*comma) { - *nextptr = comma+1; - } else { - *nextptr = NULL; - } - - return SASL_OK; -} - -static int FindBit(char *name, layer_option_t *opts) -{ - while (opts->name) { - if (!strcasecmp(name, opts->name)) { - return opts->bit; - } - - opts++; - } - - return 0; -} - -static layer_option_t *FindOptionFromBit(unsigned bit, layer_option_t *opts) -{ - while (opts->name) { - if (opts->bit == bit) { - return opts; - } - - opts++; - } - - return NULL; -} - -static int ParseOptionString(const sasl_utils_t *utils, - char *str, srp_options_t *opts, int isserver) -{ - if (!strncasecmp(str, OPTION_MDA, strlen(OPTION_MDA))) { - - int bit = FindBit(str+strlen(OPTION_MDA), digest_options); - - if (isserver && (!bit || opts->mda)) { - opts->mda = -1; - if (!bit) - utils->seterror(utils->conn, 0, - "SRP MDA %s not supported\n", - str+strlen(OPTION_MDA)); - else - SETERROR(utils, "Multiple SRP MDAs given\n"); - return SASL_BADPROT; - } - - opts->mda |= bit; - - } else if (!strcasecmp(str, OPTION_REPLAY_DETECTION)) { - if (opts->replay_detection) { - SETERROR(utils, "SRP Replay Detection option appears twice\n"); - return SASL_BADPROT; - } - opts->replay_detection = 1; - - } else if (!strncasecmp(str, OPTION_INTEGRITY, strlen(OPTION_INTEGRITY)) && - !strncasecmp(str+strlen(OPTION_INTEGRITY), "HMAC-", 5)) { - - int bit = FindBit(str+strlen(OPTION_INTEGRITY)+5, digest_options); - - if (isserver && (!bit || opts->integrity)) { - opts->integrity = -1; - if (!bit) - utils->seterror(utils->conn, 0, - "SRP Integrity option %s not supported\n", - str+strlen(OPTION_INTEGRITY)); - else - SETERROR(utils, "Multiple SRP Integrity options given\n"); - return SASL_BADPROT; - } - - opts->integrity |= bit; - - } else if (!strncasecmp(str, OPTION_CONFIDENTIALITY, - strlen(OPTION_CONFIDENTIALITY))) { - - int bit = FindBit(str+strlen(OPTION_CONFIDENTIALITY), - cipher_options); - - if (isserver && (!bit || opts->confidentiality)) { - opts->confidentiality = -1; - if (!bit) - utils->seterror(utils->conn, 0, - "SRP Confidentiality option %s not supported\n", - str+strlen(OPTION_CONFIDENTIALITY)); - else - SETERROR(utils, - "Multiple SRP Confidentiality options given\n"); - return SASL_FAIL; - } - - opts->confidentiality |= bit; - - } else if (!isserver && !strncasecmp(str, OPTION_MANDATORY, - strlen(OPTION_MANDATORY))) { - - char *layer = str+strlen(OPTION_MANDATORY); - - if (!strcasecmp(layer, OPTION_REPLAY_DETECTION)) - opts->mandatory |= BIT_REPLAY_DETECTION; - else if (!strncasecmp(layer, OPTION_INTEGRITY, - strlen(OPTION_INTEGRITY)-1)) - opts->mandatory |= BIT_INTEGRITY; - else if (!strncasecmp(layer, OPTION_CONFIDENTIALITY, - strlen(OPTION_CONFIDENTIALITY)-1)) - opts->mandatory |= BIT_CONFIDENTIALITY; - else { - utils->seterror(utils->conn, 0, - "Mandatory SRP option %s not supported\n", layer); - return SASL_BADPROT; - } - - } else if (!strncasecmp(str, OPTION_MAXBUFFERSIZE, - strlen(OPTION_MAXBUFFERSIZE))) { - - opts->maxbufsize = strtoul(str+strlen(OPTION_MAXBUFFERSIZE), NULL, 10); - - if (opts->maxbufsize > SRP_MAXBUFFERSIZE) { - utils->seterror(utils->conn, 0, - "SRP Maxbuffersize %lu too big (> %lu)\n", - opts->maxbufsize, SRP_MAXBUFFERSIZE); - return SASL_BADPROT; - } - - } else { - /* Ignore unknown options */ - } - - return SASL_OK; -} - -static int ParseOptions(const sasl_utils_t *utils, - char *in, srp_options_t *out, int isserver) -{ - int r; - - memset(out, 0, sizeof(srp_options_t)); - out->maxbufsize = SRP_MAXBUFFERSIZE; - - while (in) { - char *opt; - - r = ParseOption(utils, in, &opt, &in); - if (r) return r; - - if (opt == NULL) return SASL_OK; - - utils->log(NULL, SASL_LOG_DEBUG, "Got option: [%s]\n",opt); - - r = ParseOptionString(utils, opt, out, isserver); - utils->free(opt); - - if (r) return r; - } - - return SASL_OK; -} - -static layer_option_t *FindBest(int available, sasl_ssf_t min_ssf, - sasl_ssf_t max_ssf, layer_option_t *opts) -{ - layer_option_t *best = NULL; - - if (!available) return NULL; - - while (opts->name) { - if (opts->enabled && (available & opts->bit) && - (opts->ssf >= min_ssf) && (opts->ssf <= max_ssf) && - (!best || (opts->ssf > best->ssf))) { - best = opts; - } - - opts++; - } - - return best; -} - -static int OptionsToString(const sasl_utils_t *utils, - srp_options_t *opts, char **out) -{ - char *ret = NULL; - int alloced = 0; - int first = 1; - layer_option_t *optlist; - - ret = utils->malloc(1); - if (!ret) return SASL_NOMEM; - alloced = 1; - ret[0] = '\0'; - - optlist = digest_options; - while(optlist->name) { - if (opts->mda & optlist->bit) { - alloced += strlen(OPTION_MDA)+strlen(optlist->name)+1; - ret = utils->realloc(ret, alloced); - if (!ret) return SASL_NOMEM; - - if (!first) strcat(ret, ","); - strcat(ret, OPTION_MDA); - strcat(ret, optlist->name); - first = 0; - } - - optlist++; - } - - if (opts->replay_detection) { - alloced += strlen(OPTION_REPLAY_DETECTION)+1; - ret = utils->realloc(ret, alloced); - if (!ret) return SASL_NOMEM; - - if (!first) strcat(ret, ","); - strcat(ret, OPTION_REPLAY_DETECTION); - first = 0; - } - - optlist = digest_options; - while(optlist->name) { - if (opts->integrity & optlist->bit) { - alloced += strlen(OPTION_INTEGRITY)+5+strlen(optlist->name)+1; - ret = utils->realloc(ret, alloced); - if (!ret) return SASL_NOMEM; - - if (!first) strcat(ret, ","); - strcat(ret, OPTION_INTEGRITY); - strcat(ret, "HMAC-"); - strcat(ret, optlist->name); - first = 0; - } - - optlist++; - } - - optlist = cipher_options; - while(optlist->name) { - if (opts->confidentiality & optlist->bit) { - alloced += strlen(OPTION_CONFIDENTIALITY)+strlen(optlist->name)+1; - ret = utils->realloc(ret, alloced); - if (!ret) return SASL_NOMEM; - - if (!first) strcat(ret, ","); - strcat(ret, OPTION_CONFIDENTIALITY); - strcat(ret, optlist->name); - first = 0; - } - - optlist++; - } - - if ((opts->integrity || opts->confidentiality) && - opts->maxbufsize < SRP_MAXBUFFERSIZE) { - alloced += strlen(OPTION_MAXBUFFERSIZE)+10+1; - ret = utils->realloc(ret, alloced); - if (!ret) return SASL_NOMEM; - - if (!first) strcat(ret, ","); - strcat(ret, OPTION_MAXBUFFERSIZE); - sprintf(ret+strlen(ret), "%lu", opts->maxbufsize); - first = 0; - } - - if (opts->mandatory & BIT_REPLAY_DETECTION) { - alloced += strlen(OPTION_MANDATORY)+strlen(OPTION_REPLAY_DETECTION)+1; - ret = utils->realloc(ret, alloced); - if (!ret) return SASL_NOMEM; - - if (!first) strcat(ret, ","); - strcat(ret, OPTION_MANDATORY); - strcat(ret, OPTION_REPLAY_DETECTION); - first = 0; - } - - if (opts->mandatory & BIT_INTEGRITY) { - alloced += strlen(OPTION_MANDATORY)+strlen(OPTION_INTEGRITY)-1+1; - ret = utils->realloc(ret, alloced); - if (!ret) return SASL_NOMEM; - - if (!first) strcat(ret, ","); - strcat(ret, OPTION_MANDATORY); - strncat(ret, OPTION_INTEGRITY, strlen(OPTION_INTEGRITY)-1); - /* terminate string */ - ret[alloced-1] = '\0'; - first = 0; - } - - if (opts->mandatory & BIT_CONFIDENTIALITY) { - alloced += strlen(OPTION_MANDATORY)+strlen(OPTION_CONFIDENTIALITY)-1+1; - ret = utils->realloc(ret, alloced); - if (!ret) return SASL_NOMEM; - - if (!first) strcat(ret, ","); - strcat(ret, OPTION_MANDATORY); - strncat(ret, OPTION_CONFIDENTIALITY, strlen(OPTION_CONFIDENTIALITY)-1); - /* terminate string */ - ret[alloced-1] = '\0'; - first = 0; - } - - *out = ret; - return SASL_OK; -} - - -/* - * Set the selected MDA. - */ -static int SetMDA(srp_options_t *opts, context_t *text) -{ - layer_option_t *opt; - - opt = FindOptionFromBit(opts->mda, digest_options); - if (!opt) { - text->utils->log(NULL, SASL_LOG_ERR, - "Unable to find SRP MDA option now\n"); - return SASL_FAIL; - } - - text->md = EVP_get_digestbyname(opt->evp_name); - - return SASL_OK; -} - -/* - * Setup the selected security layer. - */ -static int LayerInit(srp_options_t *opts, context_t *text, - sasl_out_params_t *oparams, char *enc_IV, char *dec_IV, - unsigned maxbufsize) -{ - layer_option_t *opt; - - if ((opts->integrity == 0) && (opts->confidentiality == 0)) { - oparams->encode = NULL; - oparams->decode = NULL; - oparams->mech_ssf = 0; - text->utils->log(NULL, SASL_LOG_DEBUG, "Using no protection\n"); - return SASL_OK; - } - - oparams->encode = &srp_encode; - oparams->decode = &srp_decode; - oparams->maxoutbuf = opts->maxbufsize - 4; /* account for 4-byte length */ - - _plug_decode_init(&text->decode_context, text->utils, maxbufsize); - - if (opts->replay_detection) { - text->utils->log(NULL, SASL_LOG_DEBUG, "Using replay detection\n"); - - text->layer |= BIT_REPLAY_DETECTION; - - /* If no integrity layer specified, use default */ - if (!opts->integrity) - opts->integrity = default_digest->bit; - } - - if (opts->integrity) { - text->utils->log(NULL, SASL_LOG_DEBUG, "Using integrity protection\n"); - - text->layer |= BIT_INTEGRITY; - - opt = FindOptionFromBit(opts->integrity, digest_options); - if (!opt) { - text->utils->log(NULL, SASL_LOG_ERR, - "Unable to find SRP integrity layer option\n"); - return SASL_FAIL; - } - - oparams->mech_ssf = opt->ssf; - - /* Initialize the HMACs */ - text->hmac_md = EVP_get_digestbyname(opt->evp_name); - HMAC_Init(&text->hmac_send_ctx, text->K, text->Klen, text->hmac_md); - HMAC_Init(&text->hmac_recv_ctx, text->K, text->Klen, text->hmac_md); - - /* account for HMAC */ - oparams->maxoutbuf -= EVP_MD_size(text->hmac_md); - } - - if (opts->confidentiality) { - text->utils->log(NULL, SASL_LOG_DEBUG, - "Using confidentiality protection\n"); - - text->layer |= BIT_CONFIDENTIALITY; - - opt = FindOptionFromBit(opts->confidentiality, cipher_options); - if (!opt) { - text->utils->log(NULL, SASL_LOG_ERR, - "Unable to find SRP confidentiality layer option\n"); - return SASL_FAIL; - } - - oparams->mech_ssf = opt->ssf; - - /* Initialize the ciphers */ - text->cipher = EVP_get_cipherbyname(opt->evp_name); - - EVP_CIPHER_CTX_init(&text->cipher_enc_ctx); - EVP_EncryptInit(&text->cipher_enc_ctx, text->cipher, text->K, enc_IV); - - EVP_CIPHER_CTX_init(&text->cipher_dec_ctx); - EVP_DecryptInit(&text->cipher_dec_ctx, text->cipher, text->K, dec_IV); - } - - return SASL_OK; -} - -static void LayerCleanup(context_t *text) -{ - if (text->layer & BIT_INTEGRITY) { - HMAC_cleanup(&text->hmac_send_ctx); - HMAC_cleanup(&text->hmac_recv_ctx); - } - - if (text->layer & BIT_CONFIDENTIALITY) { - EVP_CIPHER_CTX_cleanup(&text->cipher_enc_ctx); - EVP_CIPHER_CTX_cleanup(&text->cipher_dec_ctx); - } -} - - -/* - * Dispose of a SRP context (could be server or client) - */ -static void srp_common_mech_dispose(void *conn_context, - const sasl_utils_t *utils) -{ - context_t *text = (context_t *) conn_context; - - if (!text) return; - - BN_clear_free(&text->N); - BN_clear_free(&text->g); - BN_clear_free(&text->v); - BN_clear_free(&text->b); - BN_clear_free(&text->B); - BN_clear_free(&text->a); - BN_clear_free(&text->A); - - if (text->authid) utils->free(text->authid); - if (text->userid) utils->free(text->userid); - if (text->free_password) _plug_free_secret(utils, &(text->password)); - if (text->salt) utils->free(text->salt); - - if (text->client_options) utils->free(text->client_options); - if (text->server_options) utils->free(text->server_options); - - LayerCleanup(text); - _plug_decode_free(&text->decode_context); - - if (text->encode_buf) utils->free(text->encode_buf); - if (text->decode_buf) utils->free(text->decode_buf); - if (text->decode_pkt_buf) utils->free(text->decode_pkt_buf); - if (text->out_buf) utils->free(text->out_buf); - - utils->free(text); -} - -static void -srp_common_mech_free(void *global_context __attribute__((unused)), - const sasl_utils_t *utils __attribute__((unused))) -{ - EVP_cleanup(); -} - - -/***************************** Server Section *****************************/ - -/* A large safe prime (N = 2q+1, where q is prime) - * - * Use N with the most bits from our table. - * - * All arithmetic is done modulo N - */ -static int generate_N_and_g(BIGNUM *N, BIGNUM *g) -{ - int result; - - BN_init(N); - result = BN_hex2bn(&N, Ng_tab[NUM_Ng-1].N); - if (!result) return SASL_FAIL; - - BN_init(g); - BN_set_word(g, Ng_tab[NUM_Ng-1].g); - - return SASL_OK; -} - -static int CalculateV(context_t *text, - BIGNUM *N, BIGNUM *g, - const char *user, - const char *pass, unsigned passlen, - BIGNUM *v, char **salt, int *saltlen) -{ - BIGNUM x; - BN_CTX *ctx = BN_CTX_new(); - int r; - - /* generate <salt> */ - *saltlen = SRP_MAXBLOCKSIZE; - *salt = (char *)text->utils->malloc(*saltlen); - if (!*salt) return SASL_NOMEM; - text->utils->rand(text->utils->rpool, *salt, *saltlen); - - r = CalculateX(text, *salt, *saltlen, user, pass, passlen, &x); - if (r) { - text->utils->seterror(text->utils->conn, 0, - "Error calculating 'x'"); - return r; - } - - /* v = g^x % N */ - BN_init(v); - BN_mod_exp(v, g, &x, N, ctx); - - BN_CTX_free(ctx); - BN_clear_free(&x); - - return r; -} - -static int CalculateB(context_t *text __attribute__((unused)), - BIGNUM *v, BIGNUM *N, BIGNUM *g, BIGNUM *b, BIGNUM *B) -{ - BIGNUM v3; - BN_CTX *ctx = BN_CTX_new(); - - /* Generate b */ - GetRandBigInt(b); - - /* Per [SRP]: make sure b > log[g](N) -- g is always 2 */ - BN_add_word(b, BN_num_bits(N)); - - /* B = (3v + g^b) % N */ - BN_init(&v3); - BN_set_word(&v3, 3); - BN_mod_mul(&v3, &v3, v, N, ctx); - BN_init(B); - BN_mod_exp(B, g, b, N, ctx); -#if OPENSSL_VERSION_NUMBER >= 0x00907000L - BN_mod_add(B, B, &v3, N, ctx); -#else - BN_add(B, B, &v3); - BN_mod(B, B, N, ctx); -#endif - - BN_CTX_free(ctx); - - return SASL_OK; -} - -static int ServerCalculateK(context_t *text, BIGNUM *v, - BIGNUM *N, BIGNUM *A, BIGNUM *b, BIGNUM *B, - char *K, int *Klen) -{ - unsigned char hash[EVP_MAX_MD_SIZE]; - int hashlen; - BIGNUM u; - BIGNUM base; - BIGNUM S; - BN_CTX *ctx = BN_CTX_new(); - int r; - - /* u = H(A | B) */ - r = MakeHash(text->md, hash, &hashlen, "%m%m", A, B); - if (r) return r; - - BN_init(&u); - BN_bin2bn(hash, hashlen, &u); - - /* S = (Av^u) ^ b % N */ - BN_init(&base); - BN_mod_exp(&base, v, &u, N, ctx); - BN_mod_mul(&base, &base, A, N, ctx); - - BN_init(&S); - BN_mod_exp(&S, &base, b, N, ctx); - - /* per Tom Wu: make sure Av^u != 1 (mod N) */ - if (BN_is_one(&base)) { - SETERROR(text->utils, "Unsafe SRP value for 'Av^u'\n"); - r = SASL_BADPROT; - goto err; - } - - /* per Tom Wu: make sure Av^u != -1 (mod N) */ - BN_add_word(&base, 1); - if (BN_cmp(&S, N) == 0) { - SETERROR(text->utils, "Unsafe SRP value for 'Av^u'\n"); - r = SASL_BADPROT; - goto err; - } - - /* K = H(S) */ - r = MakeHash(text->md, K, Klen, "%m", &S); - if (r) goto err; - - r = SASL_OK; - - err: - BN_CTX_free(ctx); - BN_clear_free(&u); - BN_clear_free(&base); - BN_clear_free(&S); - - return r; -} - -static int ParseUserSecret(const sasl_utils_t *utils, - char *secret, size_t seclen, - char **mda, BIGNUM *v, char **salt, int *saltlen) -{ - int r; - - /* The secret data is stored as suggested in RFC 2945: - * - * { utf8(mda) mpi(v) os(salt) } (base64 encoded) - */ - r = utils->decode64(secret, seclen, secret, seclen, &seclen); - - if (!r) - r = UnBuffer(utils, secret, seclen, "%s%m%o", mda, v, saltlen, salt); - if (r) { - utils->seterror(utils->conn, 0, - "Error UnBuffering user secret"); - } - - return r; -} - -static int CreateServerOptions(sasl_server_params_t *sparams, char **out) -{ - srp_options_t opts; - sasl_ssf_t limitssf, requiressf; - layer_option_t *optlist; - - /* zero out options */ - memset(&opts,0,sizeof(srp_options_t)); - - /* Add mda */ - opts.mda = server_mda->bit; - - if(sparams->props.maxbufsize == 0) { - limitssf = 0; - requiressf = 0; - } else { - if (sparams->props.max_ssf < sparams->external_ssf) { - limitssf = 0; - } else { - limitssf = sparams->props.max_ssf - sparams->external_ssf; - } - if (sparams->props.min_ssf < sparams->external_ssf) { - requiressf = 0; - } else { - requiressf = sparams->props.min_ssf - sparams->external_ssf; - } - } - - /* - * Add integrity options - * Can't advertise integrity w/o support for default HMAC - */ - if (default_digest->enabled) { - optlist = digest_options; - while(optlist->name) { - if (optlist->enabled && - /*(requiressf <= 1) &&*/ (limitssf >= 1)) { - opts.integrity |= optlist->bit; - } - optlist++; - } - } - - /* if we set any integrity options we can advertise replay detection */ - if (opts.integrity) { - opts.replay_detection = 1; - } - - /* - * Add confidentiality options - * Can't advertise confidentiality w/o support for default cipher - */ - if (default_cipher->enabled) { - optlist = cipher_options; - while(optlist->name) { - if (optlist->enabled && - (requiressf <= optlist->ssf) && - (limitssf >= optlist->ssf)) { - opts.confidentiality |= optlist->bit; - } - optlist++; - } - } - - /* Add mandatory options */ - if (requiressf >= 1) - opts.mandatory = BIT_REPLAY_DETECTION | BIT_INTEGRITY; - if (requiressf > 1) - opts.mandatory |= BIT_CONFIDENTIALITY; - - /* Add maxbuffersize */ - opts.maxbufsize = SRP_MAXBUFFERSIZE; - if (sparams->props.maxbufsize && - sparams->props.maxbufsize < opts.maxbufsize) - opts.maxbufsize = sparams->props.maxbufsize; - - return OptionsToString(sparams->utils, &opts, out); -} - -static int -srp_server_mech_new(void *glob_context __attribute__((unused)), - sasl_server_params_t *params, - const char *challenge __attribute__((unused)), - unsigned challen __attribute__((unused)), - void **conn_context) -{ - context_t *text; - - /* holds state are in */ - text = params->utils->malloc(sizeof(context_t)); - if (text == NULL) { - MEMERROR(params->utils); - return SASL_NOMEM; - } - - memset(text, 0, sizeof(context_t)); - - text->state = 1; - text->utils = params->utils; - text->md = EVP_get_digestbyname(server_mda->evp_name); - - *conn_context = text; - - return SASL_OK; -} - -static int srp_server_mech_step1(context_t *text, - sasl_server_params_t *params, - const char *clientin, - unsigned clientinlen, - const char **serverout, - unsigned *serveroutlen, - sasl_out_params_t *oparams) -{ - int result; - char *sid = NULL; - char *cn = NULL; - int cnlen; - char *realm = NULL; - char *user = NULL; - const char *password_request[] = { "*cmusaslsecretSRP", - SASL_AUX_PASSWORD, - NULL }; - struct propval auxprop_values[3]; - - /* Expect: - * - * U - authentication identity - * I - authorization identity - * sid - session id - * cn - client nonce - * - * { utf8(U) utf8(I) utf8(sid) os(cn) } - * - */ - result = UnBuffer(params->utils, clientin, clientinlen, - "%s%s%s%o", &text->authid, &text->userid, &sid, - &cnlen, &cn); - if (result) { - params->utils->seterror(params->utils->conn, 0, - "Error UnBuffering input in step 1"); - return result; - } - /* Get the realm */ - result = _plug_parseuser(params->utils, &user, &realm, params->user_realm, - params->serverFQDN, text->authid); - if (result) { - params->utils->seterror(params->utils->conn, 0, - "Error getting realm"); - goto cleanup; - } - - /* Generate N and g */ - result = generate_N_and_g(&text->N, &text->g); - if (result) { - params->utils->seterror(text->utils->conn, 0, - "Error calculating N and g"); - return result; - } - - /* Get user secret */ - result = params->utils->prop_request(params->propctx, password_request); - if (result != SASL_OK) goto cleanup; - - /* this will trigger the getting of the aux properties */ - result = params->canon_user(params->utils->conn, - text->authid, 0, SASL_CU_AUTHID, oparams); - if (result != SASL_OK) goto cleanup; - - result = params->canon_user(params->utils->conn, - text->userid, 0, SASL_CU_AUTHZID, oparams); - if (result != SASL_OK) goto cleanup; - - result = params->utils->prop_getnames(params->propctx, password_request, - auxprop_values); - if (result < 0 || - ((!auxprop_values[0].name || !auxprop_values[0].values) && - (!auxprop_values[1].name || !auxprop_values[1].values))) { - /* We didn't find this username */ - params->utils->seterror(params->utils->conn,0, - "no secret in database"); - result = params->transition ? SASL_TRANS : SASL_NOUSER; - goto cleanup; - } - - if (auxprop_values[0].name && auxprop_values[0].values) { - char *mda = NULL; - - /* We have a precomputed verifier */ - result = ParseUserSecret(params->utils, - (char*) auxprop_values[0].values[0], - auxprop_values[0].valsize, - &mda, &text->v, &text->salt, &text->saltlen); - - if (result) { - /* ParseUserSecret sets error, if any */ - if (mda) params->utils->free(mda); - goto cleanup; - } - - /* find mda */ - server_mda = digest_options; - while (server_mda->name) { - if (!strcasecmp(server_mda->name, mda)) - break; - - server_mda++; - } - - if (!server_mda->name) { - params->utils->seterror(params->utils->conn, 0, - "unknown SRP mda '%s'", mda); - params->utils->free(mda); - result = SASL_FAIL; - goto cleanup; - } - params->utils->free(mda); - - } else if (auxprop_values[1].name && auxprop_values[1].values) { - /* We only have the password -- calculate the verifier */ - int len = strlen(auxprop_values[1].values[0]); - - if (len == 0) { - params->utils->seterror(params->utils->conn,0, - "empty secret"); - result = SASL_FAIL; - goto cleanup; - } - - result = CalculateV(text, &text->N, &text->g, text->authid, - auxprop_values[1].values[0], len, - &text->v, &text->salt, &text->saltlen); - if (result) { - params->utils->seterror(params->utils->conn, 0, - "Error calculating v"); - goto cleanup; - } - } else { - params->utils->seterror(params->utils->conn, 0, - "Have neither type of secret"); - result = SASL_FAIL; - goto cleanup; - } - - /* erase the plaintext password */ - params->utils->prop_erase(params->propctx, password_request[1]); - - /* Calculate B */ - result = CalculateB(text, &text->v, &text->N, &text->g, - &text->b, &text->B); - if (result) { - params->utils->seterror(params->utils->conn, 0, - "Error calculating B"); - return result; - } - - /* Create L */ - result = CreateServerOptions(params, &text->server_options); - if (result) { - params->utils->seterror(params->utils->conn, 0, - "Error creating server options"); - goto cleanup; - } - - /* Send out: - * - * N - safe prime modulus - * g - generator - * s - salt - * B - server's public key - * L - server options (available layers etc) - * - * { 0x00 mpi(N) mpi(g) os(s) mpi(B) utf8(L) } - * - */ - result = MakeBuffer(text->utils, &text->out_buf, &text->out_buf_len, - serveroutlen, "%c%m%m%o%m%s", - 0x00, &text->N, &text->g, text->saltlen, text->salt, - &text->B, text->server_options); - if (result) { - params->utils->seterror(params->utils->conn, 0, - "Error creating SRP buffer from data in step 1"); - goto cleanup; - } - *serverout = text->out_buf; - - text->state = 2; - result = SASL_CONTINUE; - - cleanup: - if (sid) params->utils->free(sid); - if (cn) params->utils->free(cn); - if (user) params->utils->free(user); - if (realm) params->utils->free(realm); - - return result; -} - -static int srp_server_mech_step2(context_t *text, - sasl_server_params_t *params, - const char *clientin, - unsigned clientinlen, - const char **serverout, - unsigned *serveroutlen, - sasl_out_params_t *oparams) -{ - int result; - char *M1 = NULL, *cIV = NULL; /* don't free */ - int M1len, cIVlen; - srp_options_t client_opts; - char myM1[EVP_MAX_MD_SIZE]; - int myM1len; - int i; - char M2[EVP_MAX_MD_SIZE]; - int M2len; - char sIV[SRP_MAXBLOCKSIZE]; - - /* Expect: - * - * A - client's public key - * M1 - client evidence - * o - client option list - * cIV - client's initial vector - * - * { mpi(A) os(M1) utf8(o) os(cIV) } - * - */ - result = UnBuffer(params->utils, clientin, clientinlen, - "%m%-o%s%-o", &text->A, &M1len, &M1, - &text->client_options, &cIVlen, &cIV); - if (result) { - params->utils->seterror(params->utils->conn, 0, - "Error UnBuffering input in step 2"); - goto cleanup; - } - - /* Per [SRP]: reject A <= 0 */ - if (BigIntCmpWord(&text->A, 0) <= 0) { - SETERROR(params->utils, "Illegal value for 'A'\n"); - result = SASL_BADPROT; - goto cleanup; - } - - /* parse client options */ - result = ParseOptions(params->utils, text->client_options, &client_opts, 1); - if (result) { - params->utils->seterror(params->utils->conn, 0, - "Error parsing user's options"); - - if (client_opts.confidentiality) { - /* Mark that we attempted confidentiality layer negotiation */ - oparams->mech_ssf = 2; - } - else if (client_opts.integrity || client_opts.replay_detection) { - /* Mark that we attempted integrity layer negotiation */ - oparams->mech_ssf = 1; - } - return result; - } - - result = SetMDA(&client_opts, text); - if (result) { - params->utils->seterror(params->utils->conn, 0, - "Error setting options"); - return result; - } - - /* Calculate K */ - result = ServerCalculateK(text, &text->v, &text->N, &text->A, - &text->b, &text->B, text->K, &text->Klen); - if (result) { - params->utils->seterror(params->utils->conn, 0, - "Error calculating K"); - return result; - } - - /* See if M1 is correct */ - result = CalculateM1(text, &text->N, &text->g, text->authid, - text->salt, text->saltlen, &text->A, &text->B, - text->K, text->Klen, text->userid, - text->server_options, myM1, &myM1len); - if (result) { - params->utils->seterror(params->utils->conn, 0, - "Error calculating M1"); - goto cleanup; - } - - if (myM1len != M1len) { - params->utils->seterror(params->utils->conn, 0, - "SRP M1 lengths do not match"); - result = SASL_BADAUTH; - goto cleanup; - } - - for (i = 0; i < myM1len; i++) { - if (myM1[i] != M1[i]) { - params->utils->seterror(params->utils->conn, 0, - "client evidence does not match what we " - "calculated. Probably a password error"); - result = SASL_BADAUTH; - goto cleanup; - } - } - - /* calculate M2 to send */ - result = CalculateM2(text, &text->A, M1, M1len, text->K, text->Klen, - text->userid, text->client_options, "", 0, - M2, &M2len); - if (result) { - params->utils->seterror(params->utils->conn, 0, - "Error calculating M2 (server evidence)"); - goto cleanup; - } - - /* Create sIV (server initial vector) */ - text->utils->rand(text->utils->rpool, sIV, sizeof(sIV)); - - /* - * Send out: - * M2 - server evidence - * sIV - server's initial vector - * sid - session id - * ttl - time to live - * - * { os(M2) os(sIV) utf8(sid) uint(ttl) } - */ - result = MakeBuffer(text->utils, &text->out_buf, &text->out_buf_len, - serveroutlen, "%o%o%s%u", M2len, M2, - sizeof(sIV), sIV, "", 0); - if (result) { - params->utils->seterror(params->utils->conn, 0, - "Error making output buffer in SRP step 3"); - goto cleanup; - } - *serverout = text->out_buf; - - /* configure security layer */ - result = LayerInit(&client_opts, text, oparams, cIV, sIV, - params->props.maxbufsize); - if (result) { - params->utils->seterror(params->utils->conn, 0, - "Error initializing security layer"); - return result; - } - - /* set oparams */ - oparams->doneflag = 1; - oparams->param_version = 0; - - result = SASL_OK; - - cleanup: - - return result; -} - -static int srp_server_mech_step(void *conn_context, - sasl_server_params_t *sparams, - const char *clientin, - unsigned clientinlen, - const char **serverout, - unsigned *serveroutlen, - sasl_out_params_t *oparams) -{ - context_t *text = (context_t *) conn_context; - - if (!sparams - || !serverout - || !serveroutlen - || !oparams) - return SASL_BADPARAM; - - sparams->utils->log(NULL, SASL_LOG_DEBUG, - "SRP server step %d\n", text->state); - - *serverout = NULL; - *serveroutlen = 0; - - switch (text->state) { - - case 1: - return srp_server_mech_step1(text, sparams, clientin, clientinlen, - serverout, serveroutlen, oparams); - - case 2: - return srp_server_mech_step2(text, sparams, clientin, clientinlen, - serverout, serveroutlen, oparams); - - default: - sparams->utils->seterror(sparams->utils->conn, 0, - "Invalid SRP server step %d", text->state); - return SASL_FAIL; - } - - return SASL_FAIL; /* should never get here */ -} - -#ifdef DO_SRP_SETPASS -static int srp_setpass(void *glob_context __attribute__((unused)), - sasl_server_params_t *sparams, - const char *userstr, - const char *pass, - unsigned passlen __attribute__((unused)), - const char *oldpass __attribute__((unused)), - unsigned oldpasslen __attribute__((unused)), - unsigned flags) -{ - int r; - char *user = NULL; - char *user_only = NULL; - char *realm = NULL; - sasl_secret_t *sec = NULL; - struct propctx *propctx = NULL; - const char *store_request[] = { "cmusaslsecretSRP", - NULL }; - - /* Do we have a backend that can store properties? */ - if (!sparams->utils->auxprop_store || - sparams->utils->auxprop_store(NULL, NULL, NULL) != SASL_OK) { - SETERROR(sparams->utils, "SRP: auxprop backend can't store properties"); - return SASL_NOMECH; - } - - /* NB: Ideally we need to canonicalize userstr here */ - r = _plug_parseuser(sparams->utils, &user_only, &realm, sparams->user_realm, - sparams->serverFQDN, userstr); - - if (r) { - sparams->utils->seterror(sparams->utils->conn, 0, - "Error parsing user"); - return r; - } - - r = _plug_make_fulluser(sparams->utils, &user, user_only, realm); - - if (r) { - goto end; - } - - if ((flags & SASL_SET_DISABLE) || pass == NULL) { - sec = NULL; - } else { - context_t *text; - BIGNUM N; - BIGNUM g; - BIGNUM v; - char *salt; - int saltlen; - char *buffer = NULL; - int bufferlen, alloclen, encodelen; - - text = sparams->utils->malloc(sizeof(context_t)); - if (text == NULL) { - MEMERROR(sparams->utils); - return SASL_NOMEM; - } - - memset(text, 0, sizeof(context_t)); - - text->utils = sparams->utils; - text->md = EVP_get_digestbyname(server_mda->evp_name); - - r = generate_N_and_g(&N, &g); - if (r) { - sparams->utils->seterror(sparams->utils->conn, 0, - "Error calculating N and g"); - goto end; - } - - /* user is a full username here */ - r = CalculateV(text, &N, &g, user, pass, passlen, &v, &salt, &saltlen); - if (r) { - sparams->utils->seterror(sparams->utils->conn, 0, - "Error calculating v"); - goto end; - } - - /* The secret data is stored as suggested in RFC 2945: - * - * { utf8(mda) mpi(v) os(salt) } (base64 encoded) - */ - - r = MakeBuffer(text->utils, &text->out_buf, &text->out_buf_len, - &bufferlen, "%s%m%o", - server_mda->name, &v, saltlen, salt); - - if (r) { - sparams->utils->seterror(sparams->utils->conn, 0, - "Error making buffer for secret"); - goto end; - } - buffer = text->out_buf; - - /* Put 'buffer' into sasl_secret_t. - * This will be base64 encoded, so make sure its big enough. - */ - alloclen = (bufferlen/3 + 1) * 4 + 1; - sec = sparams->utils->malloc(sizeof(sasl_secret_t)+alloclen); - if (!sec) { - r = SASL_NOMEM; - goto end; - } - sparams->utils->encode64(buffer, bufferlen, sec->data, alloclen, - &encodelen); - sec->len = encodelen; - - /* Clean everything up */ - end: - if (buffer) sparams->utils->free((void *) buffer); - BN_clear_free(&N); - BN_clear_free(&g); - BN_clear_free(&v); - sparams->utils->free(text); - - if (r) return r; - } - - /* do the store */ - propctx = sparams->utils->prop_new(0); - if (!propctx) - r = SASL_FAIL; - if (!r) - r = sparams->utils->prop_request(propctx, store_request); - if (!r) - r = sparams->utils->prop_set(propctx, "cmusaslsecretSRP", - (sec ? sec->data : NULL), - (sec ? sec->len : 0)); - if (!r) - r = sparams->utils->auxprop_store(sparams->utils->conn, propctx, user); - if (propctx) - sparams->utils->prop_dispose(&propctx); - - if (r) { - sparams->utils->seterror(sparams->utils->conn, 0, - "Error putting SRP secret"); - goto cleanup; - } - - sparams->utils->log(NULL, SASL_LOG_DEBUG, "Setpass for SRP successful\n"); - - cleanup: - - if (user) _plug_free_string(sparams->utils, &user); - if (user_only) _plug_free_string(sparams->utils, &user_only); - if (realm) _plug_free_string(sparams->utils, &realm); - if (sec) _plug_free_secret(sparams->utils, &sec); - - return r; -} -#endif /* DO_SRP_SETPASS */ - -static int srp_mech_avail(void *glob_context __attribute__((unused)), - sasl_server_params_t *sparams, - void **conn_context __attribute__((unused))) -{ - /* Do we have access to the selected MDA? */ - if (!server_mda || !server_mda->enabled) { - SETERROR(sparams->utils, - "SRP unavailable due to selected MDA unavailable"); - return SASL_NOMECH; - } - - return SASL_OK; -} - -static sasl_server_plug_t srp_server_plugins[] = -{ - { - "SRP", /* mech_name */ - 0, /* max_ssf */ - SASL_SEC_NOPLAINTEXT - | SASL_SEC_NOANONYMOUS - | SASL_SEC_NOACTIVE - | SASL_SEC_NODICTIONARY - | SASL_SEC_FORWARD_SECRECY - | SASL_SEC_MUTUAL_AUTH, /* security_flags */ - SASL_FEAT_WANT_CLIENT_FIRST - | SASL_FEAT_ALLOWS_PROXY, /* features */ - NULL, /* glob_context */ - &srp_server_mech_new, /* mech_new */ - &srp_server_mech_step, /* mech_step */ - &srp_common_mech_dispose, /* mech_dispose */ - &srp_common_mech_free, /* mech_free */ -#ifdef DO_SRP_SETPASS - &srp_setpass, /* setpass */ -#else - NULL, -#endif - NULL, /* user_query */ - NULL, /* idle */ - &srp_mech_avail, /* mech avail */ - NULL /* spare */ - } -}; - -int srp_server_plug_init(const sasl_utils_t *utils, - int maxversion, - int *out_version, - const sasl_server_plug_t **pluglist, - int *plugcount, - const char *plugname __attribute__((unused))) -{ - const char *mda; - unsigned int len; - layer_option_t *opts; - - if (maxversion < SASL_SERVER_PLUG_VERSION) { - SETERROR(utils, "SRP version mismatch"); - return SASL_BADVERS; - } - - utils->getopt(utils->getopt_context, "SRP", "srp_mda", &mda, &len); - if (!mda) mda = DEFAULT_MDA; - - /* Add all digests and ciphers */ - OpenSSL_add_all_algorithms(); - - /* See which digests we have available and set max_ssf accordingly */ - opts = digest_options; - while (opts->name) { - if (EVP_get_digestbyname(opts->evp_name)) { - opts->enabled = 1; - - srp_server_plugins[0].max_ssf = opts->ssf; - } - - /* Locate the server MDA */ - if (!strcasecmp(opts->name, mda) || !strcasecmp(opts->evp_name, mda)) { - server_mda = opts; - } - - opts++; - } - - /* See which ciphers we have available and set max_ssf accordingly */ - opts = cipher_options; - while (opts->name) { - if (EVP_get_cipherbyname(opts->evp_name)) { - opts->enabled = 1; - - if (opts->ssf > srp_server_plugins[0].max_ssf) { - srp_server_plugins[0].max_ssf = opts->ssf; - } - } - - opts++; - } - - *out_version = SASL_SERVER_PLUG_VERSION; - *pluglist = srp_server_plugins; - *plugcount = 1; - - return SASL_OK; -} - -/***************************** Client Section *****************************/ - -/* Check to see if N,g is in the recommended list */ -static int check_N_and_g(const sasl_utils_t *utils, BIGNUM *N, BIGNUM *g) -{ - char *N_prime; - unsigned long g_prime; - unsigned i; - int r = SASL_FAIL; - - N_prime = BN_bn2hex(N); - g_prime = BN_get_word(g); - - for (i = 0; i < NUM_Ng; i++) { - if (!strcasecmp(N_prime, Ng_tab[i].N) && (g_prime == Ng_tab[i].g)) { - r = SASL_OK; - break; - } - } - - if (N_prime) utils->free(N_prime); - - return r; -} - -static int CalculateA(context_t *text __attribute__((unused)), - BIGNUM *N, BIGNUM *g, BIGNUM *a, BIGNUM *A) -{ - BN_CTX *ctx = BN_CTX_new(); - - /* Generate a */ - GetRandBigInt(a); - - /* Per [SRP]: make sure a > log[g](N) -- g is always 2 */ - BN_add_word(a, BN_num_bits(N)); - - /* A = g^a % N */ - BN_init(A); - BN_mod_exp(A, g, a, N, ctx); - - BN_CTX_free(ctx); - - return SASL_OK; -} - -static int ClientCalculateK(context_t *text, char *salt, int saltlen, - char *user, char *pass, int passlen, - BIGNUM *N, BIGNUM *g, BIGNUM *a, BIGNUM *A, - BIGNUM *B, char *K, int *Klen) -{ - int r; - unsigned char hash[EVP_MAX_MD_SIZE]; - int hashlen; - BIGNUM x; - BIGNUM u; - BIGNUM aux; - BIGNUM gx; - BIGNUM gx3; - BIGNUM base; - BIGNUM S; - BN_CTX *ctx = BN_CTX_new(); - - /* u = H(A | B) */ - r = MakeHash(text->md, hash, &hashlen, "%m%m", A, B); - if (r) goto err; - BN_init(&u); - BN_bin2bn(hash, hashlen, &u); - - /* per Tom Wu: make sure u != 0 */ - if (BN_is_zero(&u)) { - SETERROR(text->utils, "SRP: Illegal value for 'u'\n"); - r = SASL_BADPROT; - goto err; - } - - /* S = (B - 3(g^x)) ^ (a + ux) % N */ - - r = CalculateX(text, salt, saltlen, user, pass, passlen, &x); - if (r) return r; - - /* a + ux */ - BN_init(&aux); - BN_mul(&aux, &u, &x, ctx); - BN_add(&aux, &aux, a); - - /* gx3 = 3(g^x) % N */ - BN_init(&gx); - BN_mod_exp(&gx, g, &x, N, ctx); - BN_init(&gx3); - BN_set_word(&gx3, 3); - BN_mod_mul(&gx3, &gx3, &gx, N, ctx); - - /* base = (B - 3(g^x)) % N */ - BN_init(&base); -#if OPENSSL_VERSION_NUMBER >= 0x00907000L - BN_mod_sub(&base, B, &gx3, N, ctx); -#else - BN_sub(&base, B, &gx3); - BN_mod(&base, &base, N, ctx); - if (BigIntCmpWord(&base, 0) < 0) { - BN_add(&base, &base, N); - } -#endif - - /* S = base^aux % N */ - BN_init(&S); - BN_mod_exp(&S, &base, &aux, N, ctx); - - /* K = H(S) */ - r = MakeHash(text->md, K, Klen, "%m", &S); - if (r) goto err; - - r = SASL_OK; - - err: - BN_CTX_free(ctx); - BN_clear_free(&x); - BN_clear_free(&u); - BN_clear_free(&aux); - BN_clear_free(&gx); - BN_clear_free(&gx3); - BN_clear_free(&base); - BN_clear_free(&S); - - return r; -} - -static int CreateClientOpts(sasl_client_params_t *params, - srp_options_t *available, - srp_options_t *out) -{ - layer_option_t *opt; - sasl_ssf_t external; - sasl_ssf_t limit; - sasl_ssf_t musthave; - - /* zero out output */ - memset(out, 0, sizeof(srp_options_t)); - - params->utils->log(NULL, SASL_LOG_DEBUG, - "Available MDA = %d\n", available->mda); - - /* mda */ - opt = FindBest(available->mda, 0, 256, digest_options); - - if (opt) { - out->mda = opt->bit; - } - else { - SETERROR(params->utils, "Can't find an acceptable SRP MDA\n"); - return SASL_BADAUTH; - } - - /* get requested ssf */ - external = params->external_ssf; - - /* what do we _need_? how much is too much? */ - if(params->props.maxbufsize == 0) { - musthave = 0; - limit = 0; - } else { - if (params->props.max_ssf > external) { - limit = params->props.max_ssf - external; - } else { - limit = 0; - } - if (params->props.min_ssf > external) { - musthave = params->props.min_ssf - external; - } else { - musthave = 0; - } - } - - /* we now go searching for an option that gives us at least "musthave" - and at most "limit" bits of ssf. */ - params->utils->log(NULL, SASL_LOG_DEBUG, - "Available confidentiality = %d " - "musthave = %d limit = %d", - available->confidentiality, musthave, limit); - - /* confidentiality */ - if (limit > 1) { - - opt = FindBest(available->confidentiality, musthave, limit, - cipher_options); - - if (opt) { - out->confidentiality = opt->bit; - /* we've already satisfied the SSF with the confidentiality - * layer, but we'll also use an integrity layer if we can - */ - musthave = 0; - } - else if (musthave > 1) { - SETERROR(params->utils, - "Can't find an acceptable SRP confidentiality layer\n"); - return SASL_TOOWEAK; - } - } - - params->utils->log(NULL, SASL_LOG_DEBUG, - "Available integrity = %d " - "musthave = %d limit = %d", - available->integrity, musthave, limit); - - /* integrity */ - if ((limit >= 1) && (musthave <= 1)) { - - opt = FindBest(available->integrity, musthave, limit, - digest_options); - - if (opt) { - out->integrity = opt->bit; - - /* if we set an integrity option we can set replay detection */ - out->replay_detection = available->replay_detection; - } - else if (musthave > 0) { - SETERROR(params->utils, - "Can't find an acceptable SRP integrity layer\n"); - return SASL_TOOWEAK; - } - } - - /* Check to see if we've satisfied all of the servers mandatory layers */ - params->utils->log(NULL, SASL_LOG_DEBUG, - "Mandatory layers = %d\n",available->mandatory); - - if ((!out->replay_detection && - (available->mandatory & BIT_REPLAY_DETECTION)) || - (!out->integrity && - (available->mandatory & BIT_INTEGRITY)) || - (!out->confidentiality && - (available->mandatory & BIT_CONFIDENTIALITY))) { - SETERROR(params->utils, "Mandatory SRP layer not supported\n"); - return SASL_BADAUTH; - } - - /* Add maxbuffersize */ - out->maxbufsize = SRP_MAXBUFFERSIZE; - if (params->props.maxbufsize && params->props.maxbufsize < out->maxbufsize) - out->maxbufsize = params->props.maxbufsize; - - return SASL_OK; -} - -static int srp_client_mech_new(void *glob_context __attribute__((unused)), - sasl_client_params_t *params, - void **conn_context) -{ - context_t *text; - - /* holds state are in */ - text = params->utils->malloc(sizeof(context_t)); - if (text == NULL) { - MEMERROR( params->utils ); - return SASL_NOMEM; - } - - memset(text, 0, sizeof(context_t)); - - text->state = 1; - text->utils = params->utils; - - *conn_context = text; - - return SASL_OK; -} - -static int -srp_client_mech_step1(context_t *text, - sasl_client_params_t *params, - const char *serverin __attribute__((unused)), - unsigned serverinlen, - sasl_interact_t **prompt_need, - const char **clientout, - unsigned *clientoutlen, - sasl_out_params_t *oparams) -{ - const char *authid = NULL, *userid = NULL; - int auth_result = SASL_OK; - int pass_result = SASL_OK; - int user_result = SASL_OK; - int result; - - /* Expect: - * absolutely nothing - * - */ - if (serverinlen > 0) { - SETERROR(params->utils, "Invalid input to first step of SRP\n"); - return SASL_BADPROT; - } - - /* try to get the authid */ - if (oparams->authid==NULL) { - auth_result = _plug_get_authid(params->utils, &authid, prompt_need); - - if ((auth_result != SASL_OK) && (auth_result != SASL_INTERACT)) - return auth_result; - } - - /* try to get the userid */ - if (oparams->user == NULL) { - user_result = _plug_get_userid(params->utils, &userid, prompt_need); - - if ((user_result != SASL_OK) && (user_result != SASL_INTERACT)) - return user_result; - } - - /* try to get the password */ - if (text->password == NULL) { - pass_result=_plug_get_password(params->utils, &text->password, - &text->free_password, prompt_need); - - if ((pass_result != SASL_OK) && (pass_result != SASL_INTERACT)) - return pass_result; - } - - /* free prompts we got */ - if (prompt_need && *prompt_need) { - params->utils->free(*prompt_need); - *prompt_need = NULL; - } - - /* if there are prompts not filled in */ - if ((auth_result == SASL_INTERACT) || (user_result == SASL_INTERACT) || - (pass_result == SASL_INTERACT)) { - /* make the prompt list */ - result = - _plug_make_prompts(params->utils, prompt_need, - user_result == SASL_INTERACT ? - "Please enter your authorization name" : NULL, - NULL, - auth_result == SASL_INTERACT ? - "Please enter your authentication name" : NULL, - NULL, - pass_result == SASL_INTERACT ? - "Please enter your password" : NULL, NULL, - NULL, NULL, NULL, - NULL, NULL, NULL); - if (result != SASL_OK) return result; - - return SASL_INTERACT; - } - - if (!userid || !*userid) { - result = params->canon_user(params->utils->conn, authid, 0, - SASL_CU_AUTHID | SASL_CU_AUTHZID, oparams); - } - else { - result = params->canon_user(params->utils->conn, authid, 0, - SASL_CU_AUTHID, oparams); - if (result != SASL_OK) return result; - - result = params->canon_user(params->utils->conn, userid, 0, - SASL_CU_AUTHZID, oparams); - } - if (result != SASL_OK) return result; - - /* Send out: - * - * U - authentication identity - * I - authorization identity - * sid - previous session id - * cn - client nonce - * - * { utf8(U) utf8(I) utf8(sid) os(cn) } - */ - result = MakeBuffer(text->utils, &text->out_buf, &text->out_buf_len, - clientoutlen, "%s%s%s%o", - (char *) oparams->authid, (char *) oparams->user, - "", 0, ""); - if (result) { - params->utils->log(NULL, SASL_LOG_ERR, "Error making output buffer\n"); - goto cleanup; - } - *clientout = text->out_buf; - - text->state = 2; - - result = SASL_CONTINUE; - - cleanup: - - return result; -} - -static int -srp_client_mech_step2(context_t *text, - sasl_client_params_t *params, - const char *serverin, - unsigned serverinlen, - sasl_interact_t **prompt_need __attribute__((unused)), - const char **clientout, - unsigned *clientoutlen, - sasl_out_params_t *oparams) -{ - int result; - char reuse; - srp_options_t server_opts; - - /* Expect: - * - * { 0x00 mpi(N) mpi(g) os(s) mpi(B) utf8(L) } - */ - result = UnBuffer(params->utils, serverin, serverinlen, - "%c%m%m%o%m%s", &reuse, &text->N, &text->g, - &text->saltlen, &text->salt, &text->B, - &text->server_options); - if (result) { - params->utils->seterror(params->utils->conn, 0, - "Error UnBuffering input in step 2"); - goto cleanup; - } - - /* Check N and g to see if they are one of the recommended pairs */ - result = check_N_and_g(params->utils, &text->N, &text->g); - if (result) { - params->utils->log(NULL, SASL_LOG_ERR, - "Values of 'N' and 'g' are not recommended\n"); - goto cleanup; - } - - /* Per [SRP]: reject B <= 0, B >= N */ - if (BigIntCmpWord(&text->B, 0) <= 0 || BN_cmp(&text->B, &text->N) >= 0) { - SETERROR(params->utils, "Illegal value for 'B'\n"); - result = SASL_BADPROT; - goto cleanup; - } - - /* parse server options */ - memset(&server_opts, 0, sizeof(srp_options_t)); - result = ParseOptions(params->utils, text->server_options, &server_opts, 0); - if (result) { - params->utils->log(NULL, SASL_LOG_ERR, - "Error parsing SRP server options\n"); - goto cleanup; - } - - /* Create o */ - result = CreateClientOpts(params, &server_opts, &text->client_opts); - if (result) { - params->utils->log(NULL, SASL_LOG_ERR, - "Error creating client options\n"); - goto cleanup; - } - - result = OptionsToString(params->utils, &text->client_opts, - &text->client_options); - if (result) { - params->utils->log(NULL, SASL_LOG_ERR, - "Error converting client options to an option string\n"); - goto cleanup; - } - - result = SetMDA(&text->client_opts, text); - if (result) { - params->utils->seterror(params->utils->conn, 0, - "Error setting MDA"); - goto cleanup; - } - - /* Calculate A */ - result = CalculateA(text, &text->N, &text->g, &text->a, &text->A); - if (result) { - params->utils->seterror(params->utils->conn, 0, - "Error calculating A"); - return result; - } - - /* Calculate shared context key K */ - result = ClientCalculateK(text, text->salt, text->saltlen, - (char *) oparams->authid, - text->password->data, text->password->len, - &text->N, &text->g, &text->a, &text->A, &text->B, - text->K, &text->Klen); - if (result) { - params->utils->log(NULL, SASL_LOG_ERR, - "Error creating K\n"); - goto cleanup; - } - - /* Calculate M1 (client evidence) */ - result = CalculateM1(text, &text->N, &text->g, (char *) oparams->authid, - text->salt, text->saltlen, &text->A, &text->B, - text->K, text->Klen, (char *) oparams->user, - text->server_options, text->M1, &text->M1len); - if (result) { - params->utils->log(NULL, SASL_LOG_ERR, - "Error creating M1\n"); - goto cleanup; - } - - /* Create cIV (client initial vector) */ - text->utils->rand(text->utils->rpool, text->cIV, sizeof(text->cIV)); - - /* Send out: - * - * A - client's public key - * M1 - client evidence - * o - client option list - * cIV - client initial vector - * - * { mpi(A) os(M1) utf8(o) os(cIV) } - */ - result = MakeBuffer(text->utils, &text->out_buf, &text->out_buf_len, - clientoutlen, "%m%o%s%o", - &text->A, text->M1len, text->M1, text->client_options, - sizeof(text->cIV), text->cIV); - if (result) { - params->utils->log(NULL, SASL_LOG_ERR, "Error making output buffer\n"); - goto cleanup; - } - *clientout = text->out_buf; - - text->state = 3; - - result = SASL_CONTINUE; - - cleanup: - - return result; -} - -static int -srp_client_mech_step3(context_t *text, - sasl_client_params_t *params, - const char *serverin, - unsigned serverinlen, - sasl_interact_t **prompt_need __attribute__((unused)), - const char **clientout __attribute__((unused)), - unsigned *clientoutlen __attribute__((unused)), - sasl_out_params_t *oparams) -{ - int result; - char *M2 = NULL, *sIV = NULL; /* don't free */ - char *sid = NULL; - int M2len, sIVlen; - uint32 ttl; - int i; - char myM2[EVP_MAX_MD_SIZE]; - int myM2len; - - /* Expect: - * - * M2 - server evidence - * sIV - server initial vector - * sid - session id - * ttl - time to live - * - * { os(M2) os(sIV) utf8(sid) uint(ttl) } - */ - result = UnBuffer(params->utils, serverin, serverinlen, - "%-o%-o%s%u", &M2len, &M2, &sIVlen, &sIV, - &sid, &ttl); - if (result) { - params->utils->seterror(params->utils->conn, 0, - "Error UnBuffering input in step 3"); - goto cleanup; - } - - /* calculate our own M2 */ - result = CalculateM2(text, &text->A, text->M1, text->M1len, - text->K, text->Klen, (char *) oparams->user, - text->client_options, "", 0, - myM2, &myM2len); - if (result) { - params->utils->log(NULL, SASL_LOG_ERR, - "Error calculating our own M2 (server evidence)\n"); - goto cleanup; - } - - /* compare to see if is server spoof */ - if (myM2len != M2len) { - SETERROR(params->utils, "SRP Server M2 length wrong\n"); - result = SASL_BADSERV; - goto cleanup; - } - - - for (i = 0; i < myM2len; i++) { - if (M2[i] != myM2[i]) { - SETERROR(params->utils, - "SRP Server spoof detected. M2 incorrect\n"); - result = SASL_BADSERV; - goto cleanup; - } - } - - /* - * Send out: nothing - */ - - /* configure security layer */ - result = LayerInit(&text->client_opts, text, oparams, sIV, text->cIV, - params->props.maxbufsize); - if (result) { - params->utils->seterror(params->utils->conn, 0, - "Error initializing security layer"); - return result; - } - - /* set oparams */ - oparams->doneflag = 1; - oparams->param_version = 0; - - result = SASL_OK; - - cleanup: - if (sid) params->utils->free(sid); - - return result; -} - -static int srp_client_mech_step(void *conn_context, - sasl_client_params_t *params, - const char *serverin, - unsigned serverinlen, - sasl_interact_t **prompt_need, - const char **clientout, - unsigned *clientoutlen, - sasl_out_params_t *oparams) -{ - context_t *text = (context_t *) conn_context; - - params->utils->log(NULL, SASL_LOG_DEBUG, - "SRP client step %d\n", text->state); - - *clientout = NULL; - *clientoutlen = 0; - - switch (text->state) { - - case 1: - return srp_client_mech_step1(text, params, serverin, serverinlen, - prompt_need, clientout, clientoutlen, - oparams); - - case 2: - return srp_client_mech_step2(text, params, serverin, serverinlen, - prompt_need, clientout, clientoutlen, - oparams); - - case 3: - return srp_client_mech_step3(text, params, serverin, serverinlen, - prompt_need, clientout, clientoutlen, - oparams); - - default: - params->utils->log(NULL, SASL_LOG_ERR, - "Invalid SRP client step %d\n", text->state); - return SASL_FAIL; - } - - return SASL_FAIL; /* should never get here */ -} - - -static sasl_client_plug_t srp_client_plugins[] = -{ - { - "SRP", /* mech_name */ - 0, /* max_ssf */ - SASL_SEC_NOPLAINTEXT - | SASL_SEC_NOANONYMOUS - | SASL_SEC_NOACTIVE - | SASL_SEC_NODICTIONARY - | SASL_SEC_FORWARD_SECRECY - | SASL_SEC_MUTUAL_AUTH, /* security_flags */ - SASL_FEAT_WANT_CLIENT_FIRST - | SASL_FEAT_ALLOWS_PROXY, /* features */ - NULL, /* required_prompts */ - NULL, /* glob_context */ - &srp_client_mech_new, /* mech_new */ - &srp_client_mech_step, /* mech_step */ - &srp_common_mech_dispose, /* mech_dispose */ - &srp_common_mech_free, /* mech_free */ - NULL, /* idle */ - NULL, /* spare */ - NULL /* spare */ - } -}; - -int srp_client_plug_init(const sasl_utils_t *utils __attribute__((unused)), - int maxversion, - int *out_version, - const sasl_client_plug_t **pluglist, - int *plugcount, - const char *plugname __attribute__((unused))) -{ - layer_option_t *opts; - - if (maxversion < SASL_CLIENT_PLUG_VERSION) { - SETERROR(utils, "SRP version mismatch"); - return SASL_BADVERS; - } - - /* Add all digests and ciphers */ - OpenSSL_add_all_algorithms(); - - /* See which digests we have available and set max_ssf accordingly */ - opts = digest_options; - while (opts->name) { - if (EVP_get_digestbyname(opts->evp_name)) { - opts->enabled = 1; - - srp_client_plugins[0].max_ssf = opts->ssf; - } - - opts++; - } - - /* See which ciphers we have available and set max_ssf accordingly */ - opts = cipher_options; - while (opts->name) { - if (EVP_get_cipherbyname(opts->evp_name)) { - opts->enabled = 1; - - if (opts->ssf > srp_client_plugins[0].max_ssf) { - srp_client_plugins[0].max_ssf = opts->ssf; - } - } - - opts++; - } - - *out_version = SASL_CLIENT_PLUG_VERSION; - *pluglist = srp_client_plugins; - *plugcount=1; - - return SASL_OK; -} diff -urN cyrus-sasl-2.1.22/plugins/srp_init.c cyrus-sasl-2.1.22-no/plugins/srp_init.c --- cyrus-sasl-2.1.22/plugins/srp_init.c 2006-05-19 22:49:30.000000000 +0800 +++ cyrus-sasl-2.1.22-no/plugins/srp_init.c 1970-01-01 08:00:00.000000000 +0800 @@ -1,43 +0,0 @@ - -#include <config.h> - -#include <string.h> -#include <stdlib.h> -#include <stdio.h> -#ifndef macintosh -#include <sys/stat.h> -#endif -#include <fcntl.h> -#include <assert.h> - -#include <sasl.h> -#include <saslplug.h> -#include <saslutil.h> - -#include "plugin_common.h" - -#ifdef macintosh -#include <sasl_srp_plugin_decl.h> -#endif - -#ifdef WIN32 -BOOL APIENTRY DllMain( HANDLE hModule, - DWORD ul_reason_for_call, - LPVOID lpReserved - ) -{ - switch (ul_reason_for_call) - { - case DLL_PROCESS_ATTACH: - case DLL_THREAD_ATTACH: - case DLL_THREAD_DETACH: - case DLL_PROCESS_DETACH: - break; - } - return TRUE; -} -#endif - -SASL_CLIENT_PLUG_INIT( srp ) -SASL_SERVER_PLUG_INIT( srp ) -