17c478bd9Sstevel@tonic-gate /*
2ffc33b84SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate 
67c478bd9Sstevel@tonic-gate /*
77c478bd9Sstevel@tonic-gate  * File for ldaptool routines for SASL
87c478bd9Sstevel@tonic-gate  */
9*55fea89dSDan Cross 
107c478bd9Sstevel@tonic-gate #include <ldap.h>
117c478bd9Sstevel@tonic-gate #include "ldaptool-sasl.h"
127c478bd9Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
137c478bd9Sstevel@tonic-gate #include <sasl/sasl.h>
147c478bd9Sstevel@tonic-gate #include <locale.h>
157c478bd9Sstevel@tonic-gate #include "ldaptool.h"
167c478bd9Sstevel@tonic-gate #else
177c478bd9Sstevel@tonic-gate #include <sasl.h>
187c478bd9Sstevel@tonic-gate #endif	/* SOLARIS_LDAP_CMD */
197c478bd9Sstevel@tonic-gate #include <stdio.h>
207c478bd9Sstevel@tonic-gate 
217c478bd9Sstevel@tonic-gate #ifndef SOLARIS_LDAP_CMD
227c478bd9Sstevel@tonic-gate #define gettext(s) s
237c478bd9Sstevel@tonic-gate #endif
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate #ifdef HAVE_SASL_OPTIONS
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #define SASL_PROMPT	"SASL"
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate typedef struct {
307c478bd9Sstevel@tonic-gate         char *mech;
317c478bd9Sstevel@tonic-gate         char *authid;
327c478bd9Sstevel@tonic-gate         char *username;
337c478bd9Sstevel@tonic-gate         char *passwd;
347c478bd9Sstevel@tonic-gate         char *realm;
357c478bd9Sstevel@tonic-gate } ldaptoolSASLdefaults;
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate static int get_default(ldaptoolSASLdefaults *defaults, sasl_interact_t *interact);
387c478bd9Sstevel@tonic-gate static int get_new_value(sasl_interact_t *interact, unsigned flags);
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate void *
ldaptool_set_sasl_defaults(LDAP * ld,char * mech,char * authid,char * username,char * passwd,char * realm)417c478bd9Sstevel@tonic-gate ldaptool_set_sasl_defaults ( LDAP *ld, char *mech, char *authid, char *username,
427c478bd9Sstevel@tonic-gate 				 char *passwd, char *realm )
437c478bd9Sstevel@tonic-gate {
447c478bd9Sstevel@tonic-gate         ldaptoolSASLdefaults *defaults;
45*55fea89dSDan Cross 
467c478bd9Sstevel@tonic-gate         if ((defaults = calloc(sizeof(defaults[0]), 1)) == NULL)
477c478bd9Sstevel@tonic-gate 		return NULL;
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate 	if (mech)
507c478bd9Sstevel@tonic-gate 		defaults->mech = mech;
517c478bd9Sstevel@tonic-gate 	else
527c478bd9Sstevel@tonic-gate 		ldap_get_option(ld, LDAP_OPT_X_SASL_MECH, &defaults->mech);
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate 	if (authid)
557c478bd9Sstevel@tonic-gate 		defaults->authid = authid;
567c478bd9Sstevel@tonic-gate 	else
577c478bd9Sstevel@tonic-gate 		ldap_get_option(ld, LDAP_OPT_X_SASL_AUTHCID, &defaults->authid);
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate 	if (username)
607c478bd9Sstevel@tonic-gate 		defaults->username = username;
617c478bd9Sstevel@tonic-gate 	else
627c478bd9Sstevel@tonic-gate 		ldap_get_option(ld, LDAP_OPT_X_SASL_AUTHZID, &defaults->username);
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate         defaults->passwd = passwd;
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate 	if (realm)
677c478bd9Sstevel@tonic-gate 		defaults->realm = realm;
687c478bd9Sstevel@tonic-gate 	else
697c478bd9Sstevel@tonic-gate 		ldap_get_option(ld, LDAP_OPT_X_SASL_REALM, &defaults->realm);
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate         return defaults;
727c478bd9Sstevel@tonic-gate }
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate int
ldaptool_sasl_interact(LDAP * ld,unsigned flags,void * defaults,void * prompts)757c478bd9Sstevel@tonic-gate ldaptool_sasl_interact( LDAP *ld, unsigned flags, void *defaults, void *prompts ) {
767c478bd9Sstevel@tonic-gate 	sasl_interact_t		*interact;
777c478bd9Sstevel@tonic-gate 	ldaptoolSASLdefaults	*sasldefaults = defaults;
787c478bd9Sstevel@tonic-gate 	int			rc;
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate 	if (prompts == NULL || flags != LDAP_SASL_INTERACTIVE)
817c478bd9Sstevel@tonic-gate 		return (LDAP_PARAM_ERROR);
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate 	for (interact = prompts; interact->id != SASL_CB_LIST_END; interact++) {
847c478bd9Sstevel@tonic-gate 		/* Obtain the default value */
857c478bd9Sstevel@tonic-gate 		if ((rc = get_default(sasldefaults, interact)) != LDAP_SUCCESS)
867c478bd9Sstevel@tonic-gate 			return (rc);
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate 		/* If no default, get the new value from stdin */
897c478bd9Sstevel@tonic-gate 		if (interact->result == NULL) {
907c478bd9Sstevel@tonic-gate 			if ((rc = get_new_value(interact, flags)) != LDAP_SUCCESS)
917c478bd9Sstevel@tonic-gate 				return (rc);
927c478bd9Sstevel@tonic-gate 		}
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate 	}
957c478bd9Sstevel@tonic-gate 	return (LDAP_SUCCESS);
967c478bd9Sstevel@tonic-gate }
977c478bd9Sstevel@tonic-gate 
98*55fea89dSDan Cross static int
get_default(ldaptoolSASLdefaults * defaults,sasl_interact_t * interact)997c478bd9Sstevel@tonic-gate get_default(ldaptoolSASLdefaults *defaults, sasl_interact_t *interact) {
1007c478bd9Sstevel@tonic-gate 	const char	*defvalue = interact->defresult;
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate 	if (defaults != NULL) {
1037c478bd9Sstevel@tonic-gate 		switch( interact->id ) {
1047c478bd9Sstevel@tonic-gate         	case SASL_CB_AUTHNAME:
1057c478bd9Sstevel@tonic-gate 			defvalue = defaults->authid;
1067c478bd9Sstevel@tonic-gate 			break;
1077c478bd9Sstevel@tonic-gate         	case SASL_CB_USER:
1087c478bd9Sstevel@tonic-gate 			defvalue = defaults->username;
1097c478bd9Sstevel@tonic-gate 			break;
1107c478bd9Sstevel@tonic-gate         	case SASL_CB_PASS:
1117c478bd9Sstevel@tonic-gate 			defvalue = defaults->passwd;
1127c478bd9Sstevel@tonic-gate 			break;
1137c478bd9Sstevel@tonic-gate         	case SASL_CB_GETREALM:
1147c478bd9Sstevel@tonic-gate 			defvalue = defaults->realm;
1157c478bd9Sstevel@tonic-gate 			break;
1167c478bd9Sstevel@tonic-gate 		}
1177c478bd9Sstevel@tonic-gate 	}
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate 	if (defvalue != NULL) {
1207c478bd9Sstevel@tonic-gate 		interact->result = (char *)malloc(strlen(defvalue)+1);
1217c478bd9Sstevel@tonic-gate 		if ((char *)interact->result != NULL) {
1227c478bd9Sstevel@tonic-gate 			strcpy((char *)interact->result,defvalue);
1237c478bd9Sstevel@tonic-gate 			interact->len = strlen((char *)(interact->result));
1247c478bd9Sstevel@tonic-gate 		}
125*55fea89dSDan Cross 
1267c478bd9Sstevel@tonic-gate 		/* Clear passwd */
1277c478bd9Sstevel@tonic-gate 		if (interact->id == SASL_CB_PASS && defaults != NULL) {
1287c478bd9Sstevel@tonic-gate 			/* At this point defaults->passwd is not NULL */
1297c478bd9Sstevel@tonic-gate             		memset( defaults->passwd, '\0', strlen(defaults->passwd));
1307c478bd9Sstevel@tonic-gate 		}
1317c478bd9Sstevel@tonic-gate 
1327c478bd9Sstevel@tonic-gate 		if ((char *)interact->result == NULL) {
1337c478bd9Sstevel@tonic-gate 			return (LDAP_NO_MEMORY);
1347c478bd9Sstevel@tonic-gate 		}
1357c478bd9Sstevel@tonic-gate 	}
1367c478bd9Sstevel@tonic-gate 	return (LDAP_SUCCESS);
1377c478bd9Sstevel@tonic-gate }
1387c478bd9Sstevel@tonic-gate 
139*55fea89dSDan Cross static int
get_new_value(sasl_interact_t * interact,unsigned flags)1407c478bd9Sstevel@tonic-gate get_new_value(sasl_interact_t *interact, unsigned flags) {
1417c478bd9Sstevel@tonic-gate 	char	*newvalue, str[1024];
1427c478bd9Sstevel@tonic-gate 	int	len;
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
1457c478bd9Sstevel@tonic-gate 	char	*tmpstr;
1467c478bd9Sstevel@tonic-gate #endif
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate 	if (interact->id == SASL_CB_ECHOPROMPT || interact->id == SASL_CB_NOECHOPROMPT) {
1497c478bd9Sstevel@tonic-gate 		if (interact->challenge)
1507c478bd9Sstevel@tonic-gate 			fprintf(stderr, gettext("Challenge:%s\n"), interact->challenge);
1517c478bd9Sstevel@tonic-gate 	}
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
154*55fea89dSDan Cross 	tmpstr = ldaptool_UTF82local(interact->prompt);
1557c478bd9Sstevel@tonic-gate 	snprintf(str, sizeof(str), "%s:", tmpstr?tmpstr:SASL_PROMPT);
1567c478bd9Sstevel@tonic-gate 	if (tmpstr != NULL)
1577c478bd9Sstevel@tonic-gate 		free(tmpstr);
1587c478bd9Sstevel@tonic-gate #else
1597c478bd9Sstevel@tonic-gate #ifdef HAVE_SNPRINTF
1607c478bd9Sstevel@tonic-gate 	snprintf(str, sizeof(str), "%s:", interact->prompt?interact->prompt:SASL_PROMPT);
1617c478bd9Sstevel@tonic-gate #else
1627c478bd9Sstevel@tonic-gate 	sprintf(str, "%s:", interact->prompt?interact->prompt:SASL_PROMPT);
1637c478bd9Sstevel@tonic-gate #endif
1647c478bd9Sstevel@tonic-gate #endif	/* SOLARIS_LDAP_CMD */
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate 	/* Get the new value */
1677c478bd9Sstevel@tonic-gate 	if (interact->id == SASL_CB_PASS || interact->id == SASL_CB_NOECHOPROMPT) {
1687c478bd9Sstevel@tonic-gate #if defined(_WIN32)
1697c478bd9Sstevel@tonic-gate 		char pbuf[257];
1707c478bd9Sstevel@tonic-gate 		fputs(str,stdout);
1717c478bd9Sstevel@tonic-gate 		fflush(stdout);
1727c478bd9Sstevel@tonic-gate 		if (fgets(pbuf,256,stdin) == NULL) {
1737c478bd9Sstevel@tonic-gate 			newvalue = NULL;
1747c478bd9Sstevel@tonic-gate 		} else {
1757c478bd9Sstevel@tonic-gate 			char *tmp;
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate 			tmp = strchr(pbuf,'\n');
1787c478bd9Sstevel@tonic-gate 			if (tmp) *tmp = '\0';
1797c478bd9Sstevel@tonic-gate 			tmp = strchr(pbuf,'\r');
1807c478bd9Sstevel@tonic-gate 			if (tmp) *tmp = '\0';
1817c478bd9Sstevel@tonic-gate 			newvalue = strdup(pbuf);
1827c478bd9Sstevel@tonic-gate 		}
1837c478bd9Sstevel@tonic-gate 		if ( newvalue == NULL) {
1847c478bd9Sstevel@tonic-gate #else
1857c478bd9Sstevel@tonic-gate #if defined(SOLARIS)
1867c478bd9Sstevel@tonic-gate 		if ((newvalue = (char *)getpassphrase(str)) == NULL) {
1877c478bd9Sstevel@tonic-gate #else
1887c478bd9Sstevel@tonic-gate 		if ((newvalue = (char *)getpass(str)) == NULL) {
1897c478bd9Sstevel@tonic-gate #endif
1907c478bd9Sstevel@tonic-gate #endif
1917c478bd9Sstevel@tonic-gate 			return (LDAP_UNAVAILABLE);
1927c478bd9Sstevel@tonic-gate 		}
1937c478bd9Sstevel@tonic-gate 		len = strlen(newvalue);
1947c478bd9Sstevel@tonic-gate 	} else {
1957c478bd9Sstevel@tonic-gate 		fputs(str, stderr);
1967c478bd9Sstevel@tonic-gate 		if ((newvalue = fgets(str, sizeof(str), stdin)) == NULL)
1977c478bd9Sstevel@tonic-gate 			return (LDAP_UNAVAILABLE);
1987c478bd9Sstevel@tonic-gate 		len = strlen(str);
1997c478bd9Sstevel@tonic-gate 		if (len > 0 && str[len - 1] == '\n')
200*55fea89dSDan Cross 			str[len - 1] = 0;
2017c478bd9Sstevel@tonic-gate 	}
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate 	interact->result = (char *) strdup(newvalue);
2047c478bd9Sstevel@tonic-gate 	memset(newvalue, '\0', len);
2057c478bd9Sstevel@tonic-gate 	if (interact->result == NULL)
2067c478bd9Sstevel@tonic-gate 		return (LDAP_NO_MEMORY);
2077c478bd9Sstevel@tonic-gate 	interact->len = len;
2087c478bd9Sstevel@tonic-gate 	return (LDAP_SUCCESS);
2097c478bd9Sstevel@tonic-gate }
2107c478bd9Sstevel@tonic-gate #endif	/* HAVE_SASL_OPTIONS */
211