Home | History | Annotate | Download | only in common
      1 /*
      2  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
      3  * Use is subject to license terms.
      4  */
      5 
      6 /*
      7  * File for ldaptool routines for SASL
      8  */
      9 
     10 #include <ldap.h>
     11 #include "ldaptool-sasl.h"
     12 #ifdef SOLARIS_LDAP_CMD
     13 #include <sasl/sasl.h>
     14 #include <locale.h>
     15 #include "ldaptool.h"
     16 #else
     17 #include <sasl.h>
     18 #endif	/* SOLARIS_LDAP_CMD */
     19 #include <stdio.h>
     20 
     21 #ifndef SOLARIS_LDAP_CMD
     22 #define gettext(s) s
     23 #endif
     24 
     25 #ifdef HAVE_SASL_OPTIONS
     26 
     27 #define SASL_PROMPT	"SASL"
     28 
     29 typedef struct {
     30         char *mech;
     31         char *authid;
     32         char *username;
     33         char *passwd;
     34         char *realm;
     35 } ldaptoolSASLdefaults;
     36 
     37 static int get_default(ldaptoolSASLdefaults *defaults, sasl_interact_t *interact);
     38 static int get_new_value(sasl_interact_t *interact, unsigned flags);
     39 
     40 void *
     41 ldaptool_set_sasl_defaults ( LDAP *ld, char *mech, char *authid, char *username,
     42 				 char *passwd, char *realm )
     43 {
     44         ldaptoolSASLdefaults *defaults;
     45 
     46         if ((defaults = calloc(sizeof(defaults[0]), 1)) == NULL)
     47 		return NULL;
     48 
     49 	if (mech)
     50 		defaults->mech = mech;
     51 	else
     52 		ldap_get_option(ld, LDAP_OPT_X_SASL_MECH, &defaults->mech);
     53 
     54 	if (authid)
     55 		defaults->authid = authid;
     56 	else
     57 		ldap_get_option(ld, LDAP_OPT_X_SASL_AUTHCID, &defaults->authid);
     58 
     59 	if (username)
     60 		defaults->username = username;
     61 	else
     62 		ldap_get_option(ld, LDAP_OPT_X_SASL_AUTHZID, &defaults->username);
     63 
     64         defaults->passwd = passwd;
     65 
     66 	if (realm)
     67 		defaults->realm = realm;
     68 	else
     69 		ldap_get_option(ld, LDAP_OPT_X_SASL_REALM, &defaults->realm);
     70 
     71         return defaults;
     72 }
     73 
     74 int
     75 ldaptool_sasl_interact( LDAP *ld, unsigned flags, void *defaults, void *prompts ) {
     76 	sasl_interact_t		*interact;
     77 	ldaptoolSASLdefaults	*sasldefaults = defaults;
     78 	int			rc;
     79 
     80 	if (prompts == NULL || flags != LDAP_SASL_INTERACTIVE)
     81 		return (LDAP_PARAM_ERROR);
     82 
     83 	for (interact = prompts; interact->id != SASL_CB_LIST_END; interact++) {
     84 		/* Obtain the default value */
     85 		if ((rc = get_default(sasldefaults, interact)) != LDAP_SUCCESS)
     86 			return (rc);
     87 
     88 		/* If no default, get the new value from stdin */
     89 		if (interact->result == NULL) {
     90 			if ((rc = get_new_value(interact, flags)) != LDAP_SUCCESS)
     91 				return (rc);
     92 		}
     93 
     94 	}
     95 	return (LDAP_SUCCESS);
     96 }
     97 
     98 static int
     99 get_default(ldaptoolSASLdefaults *defaults, sasl_interact_t *interact) {
    100 	const char	*defvalue = interact->defresult;
    101 
    102 	if (defaults != NULL) {
    103 		switch( interact->id ) {
    104         	case SASL_CB_AUTHNAME:
    105 			defvalue = defaults->authid;
    106 			break;
    107         	case SASL_CB_USER:
    108 			defvalue = defaults->username;
    109 			break;
    110         	case SASL_CB_PASS:
    111 			defvalue = defaults->passwd;
    112 			break;
    113         	case SASL_CB_GETREALM:
    114 			defvalue = defaults->realm;
    115 			break;
    116 		}
    117 	}
    118 
    119 	if (defvalue != NULL) {
    120 		interact->result = (char *)malloc(strlen(defvalue)+1);
    121 		if ((char *)interact->result != NULL) {
    122 			strcpy((char *)interact->result,defvalue);
    123 			interact->len = strlen((char *)(interact->result));
    124 		}
    125 
    126 		/* Clear passwd */
    127 		if (interact->id == SASL_CB_PASS && defaults != NULL) {
    128 			/* At this point defaults->passwd is not NULL */
    129             		memset( defaults->passwd, '\0', strlen(defaults->passwd));
    130 		}
    131 
    132 		if ((char *)interact->result == NULL) {
    133 			return (LDAP_NO_MEMORY);
    134 		}
    135 	}
    136 	return (LDAP_SUCCESS);
    137 }
    138 
    139 static int
    140 get_new_value(sasl_interact_t *interact, unsigned flags) {
    141 	char	*newvalue, str[1024];
    142 	int	len;
    143 
    144 #ifdef SOLARIS_LDAP_CMD
    145 	char	*tmpstr;
    146 #endif
    147 
    148 	if (interact->id == SASL_CB_ECHOPROMPT || interact->id == SASL_CB_NOECHOPROMPT) {
    149 		if (interact->challenge)
    150 			fprintf(stderr, gettext("Challenge:%s\n"), interact->challenge);
    151 	}
    152 
    153 #ifdef SOLARIS_LDAP_CMD
    154 	tmpstr = ldaptool_UTF82local(interact->prompt);
    155 	snprintf(str, sizeof(str), "%s:", tmpstr?tmpstr:SASL_PROMPT);
    156 	if (tmpstr != NULL)
    157 		free(tmpstr);
    158 #else
    159 #ifdef HAVE_SNPRINTF
    160 	snprintf(str, sizeof(str), "%s:", interact->prompt?interact->prompt:SASL_PROMPT);
    161 #else
    162 	sprintf(str, "%s:", interact->prompt?interact->prompt:SASL_PROMPT);
    163 #endif
    164 #endif	/* SOLARIS_LDAP_CMD */
    165 
    166 	/* Get the new value */
    167 	if (interact->id == SASL_CB_PASS || interact->id == SASL_CB_NOECHOPROMPT) {
    168 #if defined(_WIN32)
    169 		char pbuf[257];
    170 		fputs(str,stdout);
    171 		fflush(stdout);
    172 		if (fgets(pbuf,256,stdin) == NULL) {
    173 			newvalue = NULL;
    174 		} else {
    175 			char *tmp;
    176 
    177 			tmp = strchr(pbuf,'\n');
    178 			if (tmp) *tmp = '\0';
    179 			tmp = strchr(pbuf,'\r');
    180 			if (tmp) *tmp = '\0';
    181 			newvalue = strdup(pbuf);
    182 		}
    183 		if ( newvalue == NULL) {
    184 #else
    185 #if defined(SOLARIS)
    186 		if ((newvalue = (char *)getpassphrase(str)) == NULL) {
    187 #else
    188 		if ((newvalue = (char *)getpass(str)) == NULL) {
    189 #endif
    190 #endif
    191 			return (LDAP_UNAVAILABLE);
    192 		}
    193 		len = strlen(newvalue);
    194 	} else {
    195 		fputs(str, stderr);
    196 		if ((newvalue = fgets(str, sizeof(str), stdin)) == NULL)
    197 			return (LDAP_UNAVAILABLE);
    198 		len = strlen(str);
    199 		if (len > 0 && str[len - 1] == '\n')
    200 			str[len - 1] = 0;
    201 	}
    202 
    203 	interact->result = (char *) strdup(newvalue);
    204 	memset(newvalue, '\0', len);
    205 	if (interact->result == NULL)
    206 		return (LDAP_NO_MEMORY);
    207 	interact->len = len;
    208 	return (LDAP_SUCCESS);
    209 }
    210 #endif	/* HAVE_SASL_OPTIONS */
    211