summaryrefslogtreecommitdiff
path: root/usr/src/lib/libldap4/common/saslbind.c
diff options
context:
space:
mode:
authorstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
committerstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
commit7c478bd95313f5f23a4c958a745db2134aa03244 (patch)
treec871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/lib/libldap4/common/saslbind.c
downloadillumos-gate-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz
OpenSolaris Launch
Diffstat (limited to 'usr/src/lib/libldap4/common/saslbind.c')
-rw-r--r--usr/src/lib/libldap4/common/saslbind.c340
1 files changed, 340 insertions, 0 deletions
diff --git a/usr/src/lib/libldap4/common/saslbind.c b/usr/src/lib/libldap4/common/saslbind.c
new file mode 100644
index 0000000000..eede4b1599
--- /dev/null
+++ b/usr/src/lib/libldap4/common/saslbind.c
@@ -0,0 +1,340 @@
+/*
+ *
+ * Copyright %G% Sun Microsystems, Inc.
+ * All Rights Reserved
+ *
+ *
+ * Comments:
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <string.h>
+
+#include "lber.h"
+#include "ldap.h"
+#include "ldap-private.h"
+#include "ldap-int.h"
+#include "sec.h"
+#include <strings.h>
+
+BerElement * ldap_build_sasl_bind_req( LDAP *ld, char *dn, char *mechanism, struct berval *creds, LDAPControl ** serverctrls)
+{
+ BerElement *ber = NULL;
+ int err;
+
+ /* Create a Bind Request for SASL authentication.
+ * It look like this :
+ * BindRequest := [APPLICATION 0] SEQUENCE {
+ * version INTEGER,
+ * name LDAPDN,
+ * authentication CHOICE {
+ * sasl [3] SEQUENCE {
+ * mechanism LDAPString,
+ * credential OCTET STRING OPTIONAL
+ * }
+ * }
+ * }
+ * all wrapped up in an LDAPMessage sequence.
+ */
+
+ if (dn == NULL || *dn == '\0'){
+ ld->ld_errno = LDAP_PARAM_ERROR;
+ return (NULLBER);
+ }
+
+
+ if ( (ber = alloc_ber_with_options( ld )) == NULLBER ) {
+ return (NULLBER);
+ }
+ if ( ber_printf( ber, "{it{ist{s", ++ld->ld_msgid, LDAP_REQ_BIND, ld->ld_version, dn, LDAP_AUTH_SASL, mechanism) == -1){
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free(ber, 1);
+ return (NULLBER);
+ }
+ if (creds != NULL && creds->bv_val != NULL) {
+ if (ber_printf(ber, "o", creds->bv_val, creds->bv_len) == -1){
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free(ber, 1);
+ return (NULLBER);
+ }
+ }
+ if (ber_printf(ber, "}}") == -1){
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULLBER );
+ }
+ /* LDAPv3 */
+ /* Code controls if any */
+ if (serverctrls && serverctrls[0]) {
+ if (ldap_controls_code(ber, serverctrls) != LDAP_SUCCESS){
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULLBER );
+ }
+ } else if (ld->ld_srvctrls && ld->ld_srvctrls[0]) {
+ /* Otherwise, is there any global server ctrls ? */
+ if (ldap_controls_code(ber, ld->ld_srvctrls) != LDAP_SUCCESS){
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULLBER );
+ }
+ }
+
+ if ( ber_printf( ber, "}" ) == -1 ) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ ber_free( ber, 1 );
+ return( NULLBER );
+ }
+
+ return (ber);
+}
+
+/*
+ * ldap_sasl_bind - bind to the ldap server (and X.500).
+ * dn, mechanism, cred, serverctrls, and clientctrls are supplied.
+ * the message id of the request is returned in msgid
+ * Returns LDAP_SUCCESS or an error code.
+ */
+
+int ldap_sasl_bind(
+ LDAP *ld,
+ char *dn,
+ char *mechanism,
+ struct berval *cred,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ int *msgidp)
+{
+ int theErr = LDAP_SUCCESS;
+ int rv;
+ BerElement *ber = NULL;
+
+ Debug ( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 1288, "ldap_sasl_bind\n"), 0,0,0);
+
+#ifdef _REENTRANT
+ LOCK_LDAP(ld);
+#endif
+ if (strcasecmp(mechanism, LDAP_SASL_SIMPLE) == 0){
+ /* Simple bind */
+ if ( (ber = ldap_build_simple_bind_req(ld, dn, cred->bv_val, serverctrls)) == NULLBER){
+ ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &theErr);
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (theErr);
+ }
+ }
+
+ if (strcasecmp(mechanism, LDAP_SASL_CRAM_MD5) == 0){
+ if (( ber = ldap_build_sasl_bind_req(ld, dn, LDAP_SASL_CRAM_MD5, cred, serverctrls)) == NULLBER) {
+ ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &theErr);
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (theErr);
+ }
+ }
+
+ if (strcasecmp(mechanism, LDAP_SASL_EXTERNAL) == 0){
+ if (( ber = ldap_build_sasl_bind_req(ld, dn, LDAP_SASL_EXTERNAL, cred, serverctrls)) == NULLBER) {
+ ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &theErr);
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (theErr);
+ }
+ }
+
+ if (strcasecmp(mechanism, LDAP_SASL_X511_PROTECTED) == 0){
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (LDAP_NOT_SUPPORTED);
+/*
+ * if (( ber = ldap_build_sasl_bind_req(ld, dn, LDAP_SASL_X511_PROTECTED, cred, serverctrls)) == NULLBER) {
+ * ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &theErr);
+ *#ifdef _REENTRANT
+ * UNLOCK_LDAP(ld);
+ *#endif
+ * return (theErr);
+ * }
+ */
+ }
+ if (strcasecmp(mechanism, LDAP_SASL_X511_STRONG) == 0){
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (LDAP_NOT_SUPPORTED);
+/*
+ * if (( ber = ldap_build_sasl_bind_req(ld, dn, LDAP_SASL_X511_PROTECTED, cred, serverctrls)) == NULLBER) {
+ * ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &theErr);
+ *#ifdef _REENTRANT
+ * UNLOCK_LDAP(ld);
+ *#endif
+ * return (theErr);
+ * }
+ */
+ }
+ if (strcasecmp(mechanism, LDAP_SASL_KERBEROS_V4) == 0){
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (LDAP_NOT_SUPPORTED);
+/*
+ * if (( ber = ldap_build_sasl_bind_req(ld, dn, LDAP_SASL_X511_PROTECTED, cred, serverctrls)) == NULLBER) {
+ * ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &theErr);
+ *#ifdef _REENTRANT
+ * UNLOCK_LDAP(ld);
+ *#endif
+ * return (theErr);
+ * }
+ */
+ }
+ if (strcasecmp(mechanism, LDAP_SASL_GSSAPI) == 0){
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (LDAP_NOT_SUPPORTED);
+/*
+ * if (( ber = ldap_build_sasl_bind_req(ld, dn, LDAP_SASL_X511_PROTECTED, cred, serverctrls)) == NULLBER) {
+ * ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &theErr);
+ *#ifdef _REENTRANT
+ * UNLOCK_LDAP(ld);
+ *#endif
+ * return (theErr);
+ * }
+ */
+ }
+ if (strcasecmp(mechanism, LDAP_SASL_SKEY) == 0){
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (LDAP_NOT_SUPPORTED);
+/*
+ * if (( ber = ldap_build_sasl_bind_req(ld, dn, LDAP_SASL_X511_PROTECTED, cred, serverctrls)) == NULLBER) {
+ * ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &theErr);
+ *#ifdef _REENTRANT
+ * UNLOCK_LDAP(ld);
+ *#endif
+ * return (theErr);
+ * }
+ */
+ }
+ if (ber == NULL){
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (LDAP_PARAM_ERROR);
+ }
+
+#ifndef NO_CACHE
+ if ( ld->ld_cache != NULL ) {
+ ldap_flush_cache( ld );
+ }
+#endif /* !NO_CACHE */
+
+ /* send the message */
+ rv = send_initial_request( ld, LDAP_REQ_BIND, dn, ber );
+ if (rv == -1){
+ rv = ld->ld_errno;
+ if (rv == LDAP_SUCCESS){
+ rv = LDAP_OTHER;
+ }
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return (rv);
+ }
+ *msgidp = rv;
+#ifdef _REENTRANT
+ UNLOCK_LDAP(ld);
+#endif
+ return ( LDAP_SUCCESS );
+}
+
+/*
+ * ldap_sasl_bind_s - bind to the ldap server (and X.500).
+ * dn, mechanism, cred, serverctrls, and clientctrls are supplied.
+ * the message id of the request is returned in msgid
+ * Returns LDAP_SUCCESS or an error code.
+ */
+
+int ldap_sasl_bind_s(
+ LDAP *ld,
+ char *dn,
+ char *mechanism,
+ struct berval *cred,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ struct berval **servercredp)
+{
+ int msgid;
+ int retcode;
+ LDAPMessage *res;
+
+ Debug ( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 1288, "ldap_sasl_bind\n"), 0,0,0);
+
+ if ((retcode = ldap_sasl_bind(ld, dn, mechanism, cred, serverctrls, clientctrls, &msgid)) != LDAP_SUCCESS)
+ return (retcode);
+ if (ldap_result(ld, msgid, 1, (struct timeval *)NULL, &res ) == -1)
+ return (ld->ld_errno );
+
+ return (ldap_parse_sasl_bind_result(ld, res, servercredp, 1));
+}
+
+int ldap_sasl_cram_md5_bind_s(
+ LDAP *ld,
+ char *dn,
+ struct berval *cred,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls )
+{
+ int res;
+ struct berval *challenge = NULL;
+ struct berval resp;
+ unsigned char digest[16];
+ char *theHDigest;
+
+ if (dn == NULL){
+ return (LDAP_PARAM_ERROR);
+ }
+
+ bzero(digest, sizeof (digest));
+
+ if ((res = ldap_sasl_bind_s(ld, dn, LDAP_SASL_CRAM_MD5, NULL, serverctrls, clientctrls, &challenge))
+ != LDAP_SASL_BIND_INPROGRESS){
+ return (res);
+ }
+ if (challenge == NULL){
+ return (LDAP_PARAM_ERROR);
+ }
+
+ Debug (LDAP_DEBUG_TRACE, "SASL challenge: %s\n", challenge->bv_val, 0, 0);
+
+ hmac_md5((unsigned char *)challenge->bv_val, challenge->bv_len,
+ (unsigned char *)cred->bv_val, cred->bv_len, digest);
+ ber_bvfree(challenge);
+ challenge = NULL;
+
+ theHDigest = hexa_print(digest, 16);
+ if (theHDigest == NULL){
+ return (LDAP_NO_MEMORY);
+ }
+
+ resp.bv_len = (strlen(dn) + 32 + 1);
+ if ((resp.bv_val = (char *)malloc(resp.bv_len+1)) == NULL) {
+ return(LDAP_NO_MEMORY);
+ }
+
+ sprintf(resp.bv_val, "%s %s", dn, theHDigest);
+ free(theHDigest);
+
+ Debug (LDAP_DEBUG_TRACE, "SASL response: %s\n", resp.bv_val, 0, 0);
+ res = ldap_sasl_bind_s(ld, dn, LDAP_SASL_CRAM_MD5, &resp, serverctrls, clientctrls, &challenge);
+
+ free(resp.bv_val);
+ return (res);
+}