2N/A * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. 2N/A/* SASL server API implementation 2N/A * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. 2N/A * Redistribution and use in source and binary forms, with or without 2N/A * modification, are permitted provided that the following conditions 2N/A * 1. Redistributions of source code must retain the above copyright 2N/A * notice, this list of conditions and the following disclaimer. 2N/A * 2. Redistributions in binary form must reproduce the above copyright 2N/A * notice, this list of conditions and the following disclaimer in 2N/A * the documentation and/or other materials provided with the 2N/A * 3. The name "Carnegie Mellon University" must not be used to 2N/A * endorse or promote products derived from this software without 2N/A * prior written permission. For permission or any other legal 2N/A * details, please contact 2N/A * Office of Technology Transfer 2N/A * Carnegie Mellon University 2N/A * 5000 Forbes Avenue 2N/A * Pittsburgh, PA 15213-3890 2N/A * (412) 268-4387, fax: (412) 268-7395 2N/A * tech-transfer@andrew.cmu.edu 2N/A * 4. Redistributions of any form whatsoever must retain the following 2N/A * "This product includes software developed by Computing Services 2N/A * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO 2N/A * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 2N/A * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE 2N/A * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 2N/A * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 2N/A * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 2N/A * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 2N/A/* gotta define gethostname ourselves on suns */ 2N/A#
endif /* !_SUN_SDK_ */ 2N/A/* Contains functions: 2N/A * server_plug_mutex ensures only one server plugin is init'ed at a time 2N/A * If a plugin is loaded more than once, the glob_context may be overwritten 2N/A * which may lead to a memory leak. We keep glob_context with each mech 2N/A * to avoid this problem. 2N/A/* if we've initialized the server sucessfully */ 2N/A/* For access by other modules */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A#
endif /* !_SUN_SDK_ */ 2N/A/* set the password for a user 2N/A * conn -- SASL connection 2N/A * pass -- plaintext password, may be NULL to remove user 2N/A * passlen -- length of password, 0 = strlen(pass) 2N/A * oldpass -- NULL will sometimes work 2N/A * oldpasslen -- length of password, 0 = strlen(oldpass) 2N/A * flags -- see flags below 2N/A * SASL_NOCHANGE -- proper entry already exists 2N/A * SASL_NOMECH -- no authdb supports password setting as configured 2N/A * SASL_NOVERIFY -- user exists, but no settable password present 2N/A * SASL_DISABLED -- account disabled 2N/A * SASL_PWLOCK -- password locked 2N/A * SASL_WEAKPASS -- password too weak for security policy 2N/A * SASL_NOUSERPASS -- user-supplied passwords not permitted 2N/A * SASL_FAIL -- OS error 2N/A * SASL_BADPARAM -- password too long 2N/A * SASL_OK -- successful 2N/A#
endif /* _SUN_SDK_ */ 2N/A /* call userdb callback function */ 2N/A "setpass callback failed for %s: %z",
2N/A "setpass callback succeeded for %s",
user);
2N/A /* now we let the mechanisms set their secrets */ 2N/A /* can't set pass for this mech */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A mechanism didn't have any user secrets 2N/A we now think it does */ 2N/A "%s: failed to set secret for %s: %z (%m)",
2N/A#
endif /* _SUN_SDK_ */ 2N/A/* local mechanism which disposes of server */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A /* set util functions - need to do rest */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A /* No sasl_conn_t was given to getcallback, so we provide the 2N/A * global callbacks structure */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A /* EXPORT DELETE START */ 2N/A /* CRYPT DELETE START */ 2N/A#
endif /* _INTEGRATED_SOLARIS_ */ 2N/A /* CRYPT DELETE END */ 2N/A /* EXPORT DELETE END */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A /* Check to see if this plugin has already been registered */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A /* call into the shared library asking for information about it */ 2N/A /* version is filled in with the version of the plugin */ 2N/A /* EXPORT DELETE START */ 2N/A /* CRYPT DELETE START */ 2N/A#
endif /* _INTEGRATED_SOLARIS_ */ 2N/A /* CRYPT DELETE END */ 2N/A /* EXPORT DELETE END */ 2N/A "server add_plugin entry_point error %z",
result);
2N/A "server add_plugin entry_point error %z\n",
result);
2N/A#
endif /* _SUN_SDK_ */ 2N/A /* Make sure plugin is using the same SASL version as us */ 2N/A "version mismatch on plugin");
2N/A#
endif /* _SUN_SDK_ */ 2N/A /* Check plugins to make sure mech_name is non-NULL */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A /* EXPORT DELETE START */ 2N/A /* CRYPT DELETE START */ 2N/A#
endif /* _INTEGRATED_SOLARIS_ */ 2N/A /* CRYPT DELETE END */ 2N/A /* EXPORT DELETE END */ 2N/A /* whether this mech actually has any users in it's db */ 2N/A /* whether this mech actually has any users in it's db */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A /* Don't de-init yet! Our refcount is nonzero. */ 2N/A /* Don't de-init yet! Our refcount is nonzero. */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A /* Free the auxprop plugins */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A /* get the path to the plugins; for now the config file will reside there */ 2N/A /* construct the filename for the config file */ 2N/A /* Check to see if anything has changed */ 2N/A /* File has not changed */ 2N/A /* No new file, nothing has changed */ 2N/A /* Ask the application if it's safe to use this file */ 2N/A /* returns continue if this file is to be skipped */ 2N/A /* returns SASL_CONTINUE if doesn't exist 2N/A * if doesn't exist we can continue using default behavior 2N/A /* get the path to the plugins; for now the config file will reside there */ 2N/A /* getpath_cb->proc MUST be a sasl_getpath_t; if only c had a type 2N/A /* length = length of path + '/' + length of appname + ".conf" + 1 2N/A /* construct the filename for the config file */ 2N/A /* Ask the application if it's safe to use this file */ 2N/A /* returns continue if this file is to be skipped */ 2N/A /* returns SASL_CONTINUE if doesn't exist 2N/A * if doesn't exist we can continue using default behavior 2N/A#
endif /* _SUN_SDK_ */ 2N/A * Verify that all the callbacks are valid 2N/A /* find end of field */ 2N/A plugin-file WS mech_name WS max_ssf *(WS security_flag) RET 2N/A /* grab mech_name */ 2N/A /* grab security flags */ 2N/A /* read security flag */ 2N/A "%s: couldn't identify flag '%s'",
2N/A /* insert mechanism into mechlist */ 2N/A#
endif /* !_SUN_SDK_ */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A/* initialize server drivers, done once per process 2N/A * callbacks -- callbacks for all server connections 2N/A * appname -- name of calling application (for config) 2N/A * callbacks -- callbacks for all server connections; must include 2N/A * appname -- name of calling application (for lower level logging) 2N/A * state -- server state 2N/A * SASL_OK -- success 2N/A * SASL_BADPARAM -- error in config file 2N/A * SASL_NOMEM -- memory failure 2N/A * SASL_BADVERS -- Mechanism version mismatch 2N/A#
endif /* _SUN_SDK_ */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A /* we require the appname to be non-null and short enough to be a path */ 2N/A /* Process only one _sasl_server_init() at a time */ 2N/A /* We're already active, just increase our refcount */ 2N/A /* xxx do something with the callback structure? */ 2N/A /* We're already active, just increase our refcount */ 2N/A /* xxx do something with the callback structure? */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A /* verify that the callbacks look ok */ 2N/A /* If we fail now, we have to call server_done */ 2N/A /* allocate mechlist and set it to empty */ 2N/A /* If we fail now, we have to call server_done */ 2N/A /* allocate mechlist and set it to empty */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A /* load config file if applicable */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A /* load internal plugins */ 2N/A/* NOTE: plugin_list option not supported in SUN SDK */ 2N/A /* delayed loading of plugins? (DSO only, as it doesn't 2N/A * make much [any] sense to delay in the static library case) */ 2N/A /* No sasl_conn_t was given to getcallback, so we provide the 2N/A * global callbacks structure */ 2N/A /* this file should contain a list of plugins available. 2N/A we'll load on demand. */ 2N/A /* Ask the application if it's safe to use this file */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A /* load all plugins now */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A * Once we have the users plaintext password we 2N/A * may want to transition them. That is put entries 2N/A * for them in the passwd database for other 2N/A * stronger mechanism 2N/A * for example PLAIN -> CRAM-MD5 2N/A /* check if this is enabled: default to false */ 2N/A/* create context for a single SASL connection 2N/A * service -- registered name of the service using SASL (e.g. "imap") 2N/A * serverFQDN -- Fully qualified domain name of server. NULL means use 2N/A * gethostname() or equivalent. 2N/A * Useful for multi-homed servers. 2N/A * user_realm -- permits multiple user realms on server, NULL = default 2N/A * iplocalport -- server IPv4/IPv6 domain literal string with port 2N/A * (if NULL, then mechanisms requiring IPaddr are disabled) 2N/A * ipremoteport -- client IPv4/IPv6 domain literal string with port 2N/A * (if NULL, then mechanisms requiring IPaddr are disabled) 2N/A * callbacks -- callbacks (e.g., authorization, lang, new getopt context) 2N/A * flags -- usage flags (see above) 2N/A * pconn -- new connection context 2N/A * SASL_OK -- success 2N/A * SASL_NOMEM -- not enough memory 2N/A#
endif /* _SUN_SDK_ */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A /* set util functions - need to do rest */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A#
else /* _SUN_SDK_ */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A /* Setup the propctx -> We'll assume the default size */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A /* the sparams is already zeroed */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A * IF mech strength + external strength < min ssf THEN FAIL 2N/A * We also have to look at the security properties and make sure 2N/A * that this mechanism has everything we want 2N/A#
endif /* _SUN_SDK_ */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A /* get the list of allowed mechanisms (default = all) */ 2N/A /* if we have a list, check the plugin against it */ 2N/A if (!*
mlist)
return 0;
/* reached EOS -> not in our list */ 2N/A /* setup parameters for the call to mech_avail */ 2N/A /* Check if we have banished this one already */ 2N/A /* If it's not mech_avail'd, then stop now */ 2N/A /* EXPORT DELETE START */ 2N/A /* CRYPT DELETE START */ 2N/A#
endif /* _INTEGRATED_SOLARIS_ */ 2N/A /* CRYPT DELETE END */ 2N/A /* EXPORT DELETE END */ 2N/A /* Generic mechanism */ 2N/A /* EXPORT DELETE START */ 2N/A /* CRYPT DELETE START */ 2N/A /* If not SUN supplied mech, it has no strength */ 2N/A /* CRYPT DELETE END */ 2N/A /* EXPORT DELETE END */ 2N/A /* EXPORT DELETE START */ 2N/A /* CRYPT DELETE START */ 2N/A#
endif /* _INTEGRATED_SOLARIS_ */ 2N/A /* CRYPT DELETE END */ 2N/A /* EXPORT DELETE END */ 2N/A#
endif /* _INTEGRATED_SOLARIS_ */ 2N/A return 0;
/* too weak */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A /* Mark this mech as no good for this connection */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A /* Error should be set by mech_avail call */ 2N/A /* Save this context */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A /* Generic mechanism */ 2N/A /* EXPORT DELETE START */ 2N/A /* CRYPT DELETE START */ 2N/A /* If not SUN supplied mech, it has no strength */ 2N/A /* CRYPT DELETE END */ 2N/A /* EXPORT DELETE END */ 2N/A /* EXPORT DELETE START */ 2N/A /* CRYPT DELETE START */ 2N/A#
endif /* _INTEGRATED_SOLARIS_ */ 2N/A /* CRYPT DELETE END */ 2N/A /* EXPORT DELETE END */ 2N/A#
endif /* _INTEGRATED_SOLARIS_ */ 2N/A return 0;
/* too weak */ 2N/A /* if there are no users in the secrets database we can't use this 2N/A#
endif /* !_SUN_SDK_ */ 2N/A /* Can it meet our features? */ 2N/A /* security properties---if there are any flags that differ and are 2N/A in what the connection are requesting, then fail */ 2N/A /* special case plaintext */ 2N/A /* if there's an external layer this is no longer plaintext */ 2N/A /* do we want to special case SASL_SEC_PASS_CREDENTIALS? nah.. */ 2N/A "security flags do not match required");
2N/A#
endif /* _INTEGRATED_SOLARIS_ */ 2N/A /* Check Features */ 2N/A /* We no longer support sasl_server_{get,put}secret */ 2N/A "mech %s requires unprovided secret facility",
2N/A "mech %s requires unprovided secret facility",
2N/A#
endif /* _SUN_SDK_ */ 2N/A * make the authorization 2N/A /* now let's see if authname is allowed to proxy for username! */ 2N/A /* check the proxy callback */ 2N/A/* start a mechanism exchange within a connection context 2N/A * mech -- the mechanism name client requested 2N/A * clientin -- client initial response (NUL terminated), NULL if empty 2N/A * clientinlen -- length of initial response 2N/A * serverout -- initial server challenge, NULL if done 2N/A * (library handles freeing this string) 2N/A * serveroutlen -- length of initial server challenge 2N/A * conn -- the sasl connection 2N/A * pconn -- the connection negotiation state on success 2N/A * Same returns as sasl_server_step() or 2N/A * SASL_NOMECH if mechanism not available. 2N/A /* make sure mech is valid mechanism 2N/A if not return appropriate error */ 2N/A /* check parameters */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A#
endif /* _INTEGRATED_SOLARIS_ */ 2N/A#
endif /*_SUN_SDK_ */ 2N/A /* Make sure that we're willing to use this mech */ 2N/A /* need to load this plugin */ 2N/A /* find the correct mechanism in this plugin */ 2N/A /* check that the parameters are the same */ 2N/A "%s: security parameters don't match mechlist file",
2N/A /* copy mechlist over */ 2N/A /* The library will eventually be freed, don't sweat it */ 2N/A#
endif /* !_SUN_SDK_ */ 2N/A /* We used to setup sparams HERE, but now it's done 2N/A inside of mech_permitted (which is called above) */ 2N/A "Got past mech_permitted with a disallowed mech!");
2N/A "Got past mech_permitted with a disallowed mech!");
2N/A#
endif /* _SUN_SDK_ */ 2N/A /* If we find it, we need to pull cur out of the 2N/A list so it won't be freed later! */ 2N/A /* Note that we don't hand over a new challenge */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A /* the work was already done by mech_avail! */ 2N/A /* Remote sent first, but mechanism does not support it. 2N/A * RFC 2222 says we fail at this point. */ 2N/A "Remote sent first but mech does not allow it.");
2N/A "Remote sent first but mech does not allow it.");
2N/A#
endif /* _SUN_SDK_ */ 2N/A /* Mech wants client-first, so let them have it */ 2N/A /* Mech wants client first anyway, so we should do that */ 2N/A /* Mech wants server-first, so let them have it */ 2N/A/* perform one step of the SASL exchange 2N/A * inputlen & input -- client data 2N/A * NULL on first step if no optional client step 2N/A * outputlen & output -- set to the server data to transmit 2N/A * to the client in the next step 2N/A * (library handles freeing this) 2N/A * SASL_OK -- exchange is complete. 2N/A * SASL_CONTINUE -- indicates another step is necessary. 2N/A * SASL_TRANS -- entry for user exists, but not for mechanism 2N/A * and transition is possible 2N/A * SASL_BADPARAM -- service name needed 2N/A * SASL_BADPROT -- invalid input from client 2N/A /* check parameters */ 2N/A /* check parameters */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A /* If we've already done the last send, return! */ 2N/A /* Don't do another step if the plugin told us that we're done */ 2N/A /* if we're done, we need to watch out for the following: 2N/A * 1. the mech does server-send-last 2N/A * 2. the protocol does not 2N/A * in this case, return SASL_CONTINUE and remember we are done. 2N/A "mech did not call canon_user for both authzid " 2N/A "mech did not call canon_user for both authzid " \
2N/A#
endif /* _SUN_SDK_ */ 2N/A/* returns the length of all the mechanisms 2N/A#
endif /* _SUN_SDK_ */ 2N/A/* This returns a list of mechanisms in a NUL-terminated string 2N/A * The default behavior is to seperate with spaces if sep==NULL 2N/A /* if there hasn't been a sasl_sever_init() fail */ 2N/A /* if there hasn't been a sasl_sever_init() fail */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A /* currently, we don't use the "user" parameter for anything */ 2N/A /* print separator */ 2N/A /* now print the mechanism name */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A#
define EOSTR(s,n) (((s)[n] ==
'\0') || ((s)[n] ==
' ') || ((s)[n] ==
'\t'))
2N/A/* returns OK if it's valid */ 2N/A /* call userdb callback function, if available */ 2N/A /* figure out how to check (i.e. auxprop or saslauthd or pwcheck) */ 2N/A /* skip to next mech in list */ 2N/A /* no mechanism available ?!? */ 2N/A#
endif /* _INTEGRATED_SOLARIS_ */ 2N/A/* check if a plaintext password is valid 2N/A * if user is NULL, check if plaintext passwords are enabled 2N/A * user -- user to query in current user_domain 2N/A * userlen -- length of username, 0 = strlen(user) 2N/A * pass -- plaintext password to check 2N/A * passlen -- length of password, 0 = strlen(pass) 2N/A * SASL_OK -- success 2N/A * SASL_NOMECH -- mechanism not supported 2N/A * SASL_NOVERIFY -- user found, but no verifier 2N/A * SASL_NOUSER -- user not found 2N/A#
else /* _SUN_SDK_ */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A /* A NULL user means the caller is checking if plaintext authentication 2N/A * is enabled. But if no connection context is supplied, we have no 2N/A * appropriate policy to check against. So for consistant global 2N/A * behavior we always say plaintext is enabled in this case. 2N/A /* Check connection security policy to see if plaintext password 2N/A * authentication is permitted. 2N/A * This should call mech_permitted with the PLAIN mechanism, 2N/A * since all plaintext mechanisms should fall under the same 2N/A * security policy guidelines. But to keep code changes and 2N/A * risk to a minimum at this juncture, we do the minimal 2N/A * security strength and plaintext policy checks which are 2N/A * most likely to be deployed and useful in the field. 2N/A /* check if it's just a query if we are enabled */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A /* canonicalize the username */ 2N/A /* Check the password */ 2N/A#
endif /* _SUN_SDK_ */ 2N/A/* check if a user exists on server 2N/A * conn -- connection context (may be NULL, used to hold last error) 2N/A * service -- registered name of the service using SASL (e.g. "imap") 2N/A * user_realm -- permits multiple user realms on server, NULL = default 2N/A * user -- NUL terminated user name 2N/A * SASL_OK -- success 2N/A * SASL_DISABLED -- account disabled [FIXME: currently not detected] 2N/A * SASL_NOUSER -- user not found 2N/A * SASL_NOVERIFY -- user found, but no usable mechanism [FIXME: not supported] 2N/A * SASL_NOMECH -- no mechanisms enabled 2N/A#
endif /* _SUN_SDK_ */ 2N/A /* figure out how to check (i.e. auxprop or saslauthd or pwcheck) */ 2N/A /* skip to next mech in list */ 2N/A /* Screen out the SASL_BADPARAM response 2N/A * we'll get from not giving a password */ 2N/A /* no mechanism available ?!? */ 2N/A#
endif /* !_SUN_SDK_ */ 2N/A/* check if an apop exchange is valid 2N/A * (note this is an optional part of the SASL API) 2N/A * if challenge is NULL, just check if APOP is enabled 2N/A * challenge -- challenge which was sent to client 2N/A * challen -- length of challenge, 0 = strlen(challenge) 2N/A * response -- client response, "<user> <digest>" (RFC 1939) 2N/A * resplen -- length of response, 0 = strlen(response) 2N/A * SASL_OK -- success 2N/A * SASL_BADAUTH -- authentication failed 2N/A * SASL_BADPARAM -- missing challenge 2N/A * SASL_BADPROT -- protocol error (e.g., response in wrong format) 2N/A * SASL_NOVERIFY -- user found, but no verifier 2N/A * SASL_NOMECH -- mechanism not supported 2N/A * SASL_NOUSER -- user not found 2N/A#
endif /* _SUN_SDK_ */ 2N/A /* check if it's just a query if we are enabled */ 2N/A /* Parse out username and digest. 2N/A * Per RFC 1939, response must be "<user> <digest>", where 2N/A * <digest> is a 16-octet value which is sent in hexadecimal 2N/A * format, using lower-case ASCII characters. 2N/A#
endif /* _INTEGRATED_SOLARIS_ */ 2N/A /* Do APOP verification */ 2N/A /* If verification failed, we don't want to encourage getprop to work */ 2N/A#
else /* sasl_checkapop was disabled at compile time */ 2N/A "sasl_checkapop called, but was disabled at compile time");
2N/A#
endif /* DO_SASL_CHECKAPOP */