10Sstevel@tonic-gate /*
2*8097SSreedhar.Chalamalasetti@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
30Sstevel@tonic-gate * Use is subject to license terms.
40Sstevel@tonic-gate */
50Sstevel@tonic-gate
60Sstevel@tonic-gate /*
70Sstevel@tonic-gate * File for ldaptool routines for SASL
80Sstevel@tonic-gate */
90Sstevel@tonic-gate
100Sstevel@tonic-gate #include <ldap.h>
110Sstevel@tonic-gate #include "ldaptool-sasl.h"
120Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
130Sstevel@tonic-gate #include <sasl/sasl.h>
140Sstevel@tonic-gate #include <locale.h>
150Sstevel@tonic-gate #include "ldaptool.h"
160Sstevel@tonic-gate #else
170Sstevel@tonic-gate #include <sasl.h>
180Sstevel@tonic-gate #endif /* SOLARIS_LDAP_CMD */
190Sstevel@tonic-gate #include <stdio.h>
200Sstevel@tonic-gate
210Sstevel@tonic-gate #ifndef SOLARIS_LDAP_CMD
220Sstevel@tonic-gate #define gettext(s) s
230Sstevel@tonic-gate #endif
240Sstevel@tonic-gate
250Sstevel@tonic-gate #ifdef HAVE_SASL_OPTIONS
260Sstevel@tonic-gate
270Sstevel@tonic-gate #define SASL_PROMPT "SASL"
280Sstevel@tonic-gate
290Sstevel@tonic-gate typedef struct {
300Sstevel@tonic-gate char *mech;
310Sstevel@tonic-gate char *authid;
320Sstevel@tonic-gate char *username;
330Sstevel@tonic-gate char *passwd;
340Sstevel@tonic-gate char *realm;
350Sstevel@tonic-gate } ldaptoolSASLdefaults;
360Sstevel@tonic-gate
370Sstevel@tonic-gate static int get_default(ldaptoolSASLdefaults *defaults, sasl_interact_t *interact);
380Sstevel@tonic-gate static int get_new_value(sasl_interact_t *interact, unsigned flags);
390Sstevel@tonic-gate
400Sstevel@tonic-gate void *
ldaptool_set_sasl_defaults(LDAP * ld,char * mech,char * authid,char * username,char * passwd,char * realm)410Sstevel@tonic-gate ldaptool_set_sasl_defaults ( LDAP *ld, char *mech, char *authid, char *username,
420Sstevel@tonic-gate char *passwd, char *realm )
430Sstevel@tonic-gate {
440Sstevel@tonic-gate ldaptoolSASLdefaults *defaults;
450Sstevel@tonic-gate
460Sstevel@tonic-gate if ((defaults = calloc(sizeof(defaults[0]), 1)) == NULL)
470Sstevel@tonic-gate return NULL;
480Sstevel@tonic-gate
490Sstevel@tonic-gate if (mech)
500Sstevel@tonic-gate defaults->mech = mech;
510Sstevel@tonic-gate else
520Sstevel@tonic-gate ldap_get_option(ld, LDAP_OPT_X_SASL_MECH, &defaults->mech);
530Sstevel@tonic-gate
540Sstevel@tonic-gate if (authid)
550Sstevel@tonic-gate defaults->authid = authid;
560Sstevel@tonic-gate else
570Sstevel@tonic-gate ldap_get_option(ld, LDAP_OPT_X_SASL_AUTHCID, &defaults->authid);
580Sstevel@tonic-gate
590Sstevel@tonic-gate if (username)
600Sstevel@tonic-gate defaults->username = username;
610Sstevel@tonic-gate else
620Sstevel@tonic-gate ldap_get_option(ld, LDAP_OPT_X_SASL_AUTHZID, &defaults->username);
630Sstevel@tonic-gate
640Sstevel@tonic-gate defaults->passwd = passwd;
650Sstevel@tonic-gate
660Sstevel@tonic-gate if (realm)
670Sstevel@tonic-gate defaults->realm = realm;
680Sstevel@tonic-gate else
690Sstevel@tonic-gate ldap_get_option(ld, LDAP_OPT_X_SASL_REALM, &defaults->realm);
700Sstevel@tonic-gate
710Sstevel@tonic-gate return defaults;
720Sstevel@tonic-gate }
730Sstevel@tonic-gate
740Sstevel@tonic-gate int
ldaptool_sasl_interact(LDAP * ld,unsigned flags,void * defaults,void * prompts)750Sstevel@tonic-gate ldaptool_sasl_interact( LDAP *ld, unsigned flags, void *defaults, void *prompts ) {
760Sstevel@tonic-gate sasl_interact_t *interact;
770Sstevel@tonic-gate ldaptoolSASLdefaults *sasldefaults = defaults;
780Sstevel@tonic-gate int rc;
790Sstevel@tonic-gate
800Sstevel@tonic-gate if (prompts == NULL || flags != LDAP_SASL_INTERACTIVE)
810Sstevel@tonic-gate return (LDAP_PARAM_ERROR);
820Sstevel@tonic-gate
830Sstevel@tonic-gate for (interact = prompts; interact->id != SASL_CB_LIST_END; interact++) {
840Sstevel@tonic-gate /* Obtain the default value */
850Sstevel@tonic-gate if ((rc = get_default(sasldefaults, interact)) != LDAP_SUCCESS)
860Sstevel@tonic-gate return (rc);
870Sstevel@tonic-gate
880Sstevel@tonic-gate /* If no default, get the new value from stdin */
890Sstevel@tonic-gate if (interact->result == NULL) {
900Sstevel@tonic-gate if ((rc = get_new_value(interact, flags)) != LDAP_SUCCESS)
910Sstevel@tonic-gate return (rc);
920Sstevel@tonic-gate }
930Sstevel@tonic-gate
940Sstevel@tonic-gate }
950Sstevel@tonic-gate return (LDAP_SUCCESS);
960Sstevel@tonic-gate }
970Sstevel@tonic-gate
980Sstevel@tonic-gate static int
get_default(ldaptoolSASLdefaults * defaults,sasl_interact_t * interact)990Sstevel@tonic-gate get_default(ldaptoolSASLdefaults *defaults, sasl_interact_t *interact) {
1000Sstevel@tonic-gate const char *defvalue = interact->defresult;
1010Sstevel@tonic-gate
1020Sstevel@tonic-gate if (defaults != NULL) {
1030Sstevel@tonic-gate switch( interact->id ) {
1040Sstevel@tonic-gate case SASL_CB_AUTHNAME:
1050Sstevel@tonic-gate defvalue = defaults->authid;
1060Sstevel@tonic-gate break;
1070Sstevel@tonic-gate case SASL_CB_USER:
1080Sstevel@tonic-gate defvalue = defaults->username;
1090Sstevel@tonic-gate break;
1100Sstevel@tonic-gate case SASL_CB_PASS:
1110Sstevel@tonic-gate defvalue = defaults->passwd;
1120Sstevel@tonic-gate break;
1130Sstevel@tonic-gate case SASL_CB_GETREALM:
1140Sstevel@tonic-gate defvalue = defaults->realm;
1150Sstevel@tonic-gate break;
1160Sstevel@tonic-gate }
1170Sstevel@tonic-gate }
1180Sstevel@tonic-gate
1190Sstevel@tonic-gate if (defvalue != NULL) {
1200Sstevel@tonic-gate interact->result = (char *)malloc(strlen(defvalue)+1);
1210Sstevel@tonic-gate if ((char *)interact->result != NULL) {
1220Sstevel@tonic-gate strcpy((char *)interact->result,defvalue);
1230Sstevel@tonic-gate interact->len = strlen((char *)(interact->result));
1240Sstevel@tonic-gate }
1250Sstevel@tonic-gate
1260Sstevel@tonic-gate /* Clear passwd */
1270Sstevel@tonic-gate if (interact->id == SASL_CB_PASS && defaults != NULL) {
1280Sstevel@tonic-gate /* At this point defaults->passwd is not NULL */
1290Sstevel@tonic-gate memset( defaults->passwd, '\0', strlen(defaults->passwd));
1300Sstevel@tonic-gate }
1310Sstevel@tonic-gate
1320Sstevel@tonic-gate if ((char *)interact->result == NULL) {
1330Sstevel@tonic-gate return (LDAP_NO_MEMORY);
1340Sstevel@tonic-gate }
1350Sstevel@tonic-gate }
1360Sstevel@tonic-gate return (LDAP_SUCCESS);
1370Sstevel@tonic-gate }
1380Sstevel@tonic-gate
1390Sstevel@tonic-gate static int
get_new_value(sasl_interact_t * interact,unsigned flags)1400Sstevel@tonic-gate get_new_value(sasl_interact_t *interact, unsigned flags) {
1410Sstevel@tonic-gate char *newvalue, str[1024];
1420Sstevel@tonic-gate int len;
1430Sstevel@tonic-gate
1440Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
1450Sstevel@tonic-gate char *tmpstr;
1460Sstevel@tonic-gate #endif
1470Sstevel@tonic-gate
1480Sstevel@tonic-gate if (interact->id == SASL_CB_ECHOPROMPT || interact->id == SASL_CB_NOECHOPROMPT) {
1490Sstevel@tonic-gate if (interact->challenge)
1500Sstevel@tonic-gate fprintf(stderr, gettext("Challenge:%s\n"), interact->challenge);
1510Sstevel@tonic-gate }
1520Sstevel@tonic-gate
1530Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
1540Sstevel@tonic-gate tmpstr = ldaptool_UTF82local(interact->prompt);
1550Sstevel@tonic-gate snprintf(str, sizeof(str), "%s:", tmpstr?tmpstr:SASL_PROMPT);
1560Sstevel@tonic-gate if (tmpstr != NULL)
1570Sstevel@tonic-gate free(tmpstr);
1580Sstevel@tonic-gate #else
1590Sstevel@tonic-gate #ifdef HAVE_SNPRINTF
1600Sstevel@tonic-gate snprintf(str, sizeof(str), "%s:", interact->prompt?interact->prompt:SASL_PROMPT);
1610Sstevel@tonic-gate #else
1620Sstevel@tonic-gate sprintf(str, "%s:", interact->prompt?interact->prompt:SASL_PROMPT);
1630Sstevel@tonic-gate #endif
1640Sstevel@tonic-gate #endif /* SOLARIS_LDAP_CMD */
1650Sstevel@tonic-gate
1660Sstevel@tonic-gate /* Get the new value */
1670Sstevel@tonic-gate if (interact->id == SASL_CB_PASS || interact->id == SASL_CB_NOECHOPROMPT) {
1680Sstevel@tonic-gate #if defined(_WIN32)
1690Sstevel@tonic-gate char pbuf[257];
1700Sstevel@tonic-gate fputs(str,stdout);
1710Sstevel@tonic-gate fflush(stdout);
1720Sstevel@tonic-gate if (fgets(pbuf,256,stdin) == NULL) {
1730Sstevel@tonic-gate newvalue = NULL;
1740Sstevel@tonic-gate } else {
1750Sstevel@tonic-gate char *tmp;
1760Sstevel@tonic-gate
1770Sstevel@tonic-gate tmp = strchr(pbuf,'\n');
1780Sstevel@tonic-gate if (tmp) *tmp = '\0';
1790Sstevel@tonic-gate tmp = strchr(pbuf,'\r');
1800Sstevel@tonic-gate if (tmp) *tmp = '\0';
1810Sstevel@tonic-gate newvalue = strdup(pbuf);
1820Sstevel@tonic-gate }
1830Sstevel@tonic-gate if ( newvalue == NULL) {
1840Sstevel@tonic-gate #else
1850Sstevel@tonic-gate #if defined(SOLARIS)
1860Sstevel@tonic-gate if ((newvalue = (char *)getpassphrase(str)) == NULL) {
1870Sstevel@tonic-gate #else
1880Sstevel@tonic-gate if ((newvalue = (char *)getpass(str)) == NULL) {
1890Sstevel@tonic-gate #endif
1900Sstevel@tonic-gate #endif
1910Sstevel@tonic-gate return (LDAP_UNAVAILABLE);
1920Sstevel@tonic-gate }
1930Sstevel@tonic-gate len = strlen(newvalue);
1940Sstevel@tonic-gate } else {
1950Sstevel@tonic-gate fputs(str, stderr);
1960Sstevel@tonic-gate if ((newvalue = fgets(str, sizeof(str), stdin)) == NULL)
1970Sstevel@tonic-gate return (LDAP_UNAVAILABLE);
1980Sstevel@tonic-gate len = strlen(str);
1990Sstevel@tonic-gate if (len > 0 && str[len - 1] == '\n')
2000Sstevel@tonic-gate str[len - 1] = 0;
2010Sstevel@tonic-gate }
2020Sstevel@tonic-gate
2030Sstevel@tonic-gate interact->result = (char *) strdup(newvalue);
2040Sstevel@tonic-gate memset(newvalue, '\0', len);
2050Sstevel@tonic-gate if (interact->result == NULL)
2060Sstevel@tonic-gate return (LDAP_NO_MEMORY);
2070Sstevel@tonic-gate interact->len = len;
2080Sstevel@tonic-gate return (LDAP_SUCCESS);
2090Sstevel@tonic-gate }
2100Sstevel@tonic-gate #endif /* HAVE_SASL_OPTIONS */
211