17c478bd9Sstevel@tonic-gate /*
2*ffc33b84SSreedhar 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 */
97c478bd9Sstevel@tonic-gate
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;
457c478bd9Sstevel@tonic-gate
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
987c478bd9Sstevel@tonic-gate 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 }
1257c478bd9Sstevel@tonic-gate
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
1397c478bd9Sstevel@tonic-gate 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
1547c478bd9Sstevel@tonic-gate 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')
2007c478bd9Sstevel@tonic-gate 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