Home | History | Annotate | Line # | Download | only in lib
      1 /*
      2  * The Initial Developer of the Original Code is International
      3  * Business Machines Corporation. Portions created by IBM
      4  * Corporation are Copyright (C) 2005 International Business
      5  * Machines Corporation. All Rights Reserved.
      6  *
      7  * This program is free software; you can redistribute it and/or modify
      8  * it under the terms of the Common Public License as published by
      9  * IBM Corporation; either version 1 of the License, or (at your option)
     10  * any later version.
     11  *
     12  * This program is distributed in the hope that it will be useful,
     13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15  * Common Public License for more details.
     16  *
     17  * You should have received a copy of the Common Public License
     18  * along with this program; if not, a copy can be viewed at
     19  * http://www.opensource.org/licenses/cpl1.0.php.
     20  */
     21 
     22 #include "config.h"
     23 #include <unistd.h>
     24 #include <stdlib.h>
     25 #include <trousers/tss.h>
     26 #include <trousers/trousers.h>
     27 
     28 #include "tpm_tspi.h"
     29 #include "tpm_utils.h"
     30 
     31 BOOL useUnicode = FALSE;
     32 
     33 static const struct option sGenLongOpts[] = {
     34 	{ "help", no_argument, NULL, 'h' },
     35 	{ "version", no_argument, NULL, 'v' },
     36 	{ "log", required_argument, NULL, 'l' },
     37 	{ "unicode", no_argument, NULL, 'u' },
     38 };
     39 
     40 static const char *pszGenShortOpts = "hvl:u";
     41 
     42 void initIntlSys( ) {
     43 
     44 	setlocale( LC_ALL, "" );
     45 	bindtextdomain( PACKAGE, LOCALEDIR );
     46 	textdomain( PACKAGE );
     47 }
     48 
     49 int
     50 genericOptHandler( int a_iNumArgs, char **a_pszArgs,
     51 		   const char *a_pszShortOpts,
     52 		   struct option *a_sLongOpts, int a_iNumOpts,
     53 		   CmdOptParser a_tCmdOptParser, CmdHelpFunction a_tCmdHelpFunction ) {
     54 
     55 	CmdHelpFunction  tCmdHelp = ( a_tCmdHelpFunction ) ? a_tCmdHelpFunction
     56 							   : logCmdHelp;
     57 
     58 	char  szShortOpts[strlen( pszGenShortOpts )
     59 			  + ( ( a_pszShortOpts == NULL ) ? 0 : strlen( a_pszShortOpts ) )
     60 			  + 1];
     61 
     62 	int            iNumGenLongOpts = sizeof( sGenLongOpts ) / sizeof( struct option );
     63 	struct option  sLongOpts[iNumGenLongOpts + a_iNumOpts + 1];
     64 
     65 	int  iOpt;
     66 	int  rc;
     67 
     68 	strcpy( szShortOpts, pszGenShortOpts);
     69 	if ( a_pszShortOpts )
     70 		strcat( szShortOpts, a_pszShortOpts );
     71 
     72 	__memset( sLongOpts, 0, sizeof( sLongOpts ) );
     73 	memcpy( sLongOpts, sGenLongOpts, sizeof( sGenLongOpts ) );
     74 	if ( a_sLongOpts ) {
     75 		memcpy( sLongOpts + iNumGenLongOpts,
     76 			a_sLongOpts,
     77 			a_iNumOpts * sizeof( struct option ) );
     78 	}
     79 
     80 	while ( ( iOpt = getopt_long( a_iNumArgs, a_pszArgs,
     81 					szShortOpts, sLongOpts, NULL ) ) != -1 ) {
     82 
     83 		switch ( iOpt ) {
     84 			case 'h':
     85 				tCmdHelp( a_pszArgs[0] );
     86 				return -1;
     87 
     88 			case 'v':
     89 				logMsg( _("%s version: %s\n"), a_pszArgs[0], CMD_VERSION );
     90 				return -1;
     91 
     92 			case 'l':
     93 				if ( !optarg ) {
     94 					tCmdHelp( a_pszArgs[0] );
     95 					return -1;
     96 				}
     97 
     98 				if ( strcmp( optarg, LOG_NONE ) == 0 )
     99 					iLogLevel = LOG_LEVEL_NONE;
    100 				else if ( strcmp( optarg, LOG_ERROR ) == 0 )
    101 					iLogLevel = LOG_LEVEL_ERROR;
    102 				else if ( strcmp( optarg, LOG_INFO ) == 0 )
    103 					iLogLevel = LOG_LEVEL_INFO;
    104 				else if ( strcmp( optarg, LOG_DEBUG ) == 0 )
    105 					iLogLevel = LOG_LEVEL_DEBUG;
    106 				else {
    107 					logMsg( _("Valid log levels are: %s, %s, %s, %s\n"),
    108 						LOG_NONE,
    109 						LOG_ERROR,
    110 						LOG_INFO,
    111 						LOG_DEBUG );
    112 					tCmdHelp( a_pszArgs[0] );
    113 					return -1;
    114 				}
    115 				break;
    116 			case 'u':
    117 				useUnicode = TRUE;
    118 				break;
    119 			case '?':
    120 				tCmdHelp( a_pszArgs[0] );
    121 				return -1;
    122 
    123 			default:
    124 				if ( !a_tCmdOptParser )
    125 					return -1;
    126 
    127 				rc = a_tCmdOptParser( iOpt, optarg );
    128 				if ( rc != 0 )
    129 					return rc;
    130 				break;
    131 		}
    132 	}
    133 
    134 	return 0;
    135 }
    136 
    137 void * __no_optimize
    138 __memset(void *s, int c, size_t n)
    139 {
    140 	return memset(s, c, n);
    141 }
    142 
    143 /*
    144  * This function should be called when you are done with a password
    145  * the above getPasswd function to properly clean up.
    146  */
    147 void shredPasswd( char *a_pszPasswd ) {
    148 
    149 	if ( a_pszPasswd ) {
    150 		__memset( a_pszPasswd, 0, strlen( a_pszPasswd ) );
    151 		free( a_pszPasswd );
    152 	}
    153 }
    154 
    155 /*
    156  * You must free the memory passed back to you when you are finished.
    157  * Loop will always terminate by the second pass.
    158  * Safest use of getpass is to zero the memory as soon as possible.
    159  */
    160 char *getPlainPasswd(const char *a_pszPrompt, BOOL a_bConfirm) {
    161 	int len;
    162 	return _getPasswd(a_pszPrompt, &len, a_bConfirm, FALSE);
    163 }
    164 
    165 #ifndef TSS_LIB_IS_12
    166 char *getPasswd(const char *a_pszPrompt, int* a_iLen,
    167 		BOOL a_bConfirm) {
    168 	return _getPasswd( a_pszPrompt, a_iLen, a_bConfirm, useUnicode);
    169 }
    170 #endif
    171 char *_getPasswd(const char *a_pszPrompt, int* a_iLen,
    172 		BOOL a_bConfirm, BOOL a_bUseUnicode) {
    173 
    174 	char *pszPrompt = (char *)a_pszPrompt;
    175 	char *pszPasswd = NULL;
    176 	char *pszRetPasswd = NULL;
    177 
    178 	do {
    179 		// Get password value from user - this is a static buffer
    180 		// and should never be freed
    181 		pszPasswd = getpass( pszPrompt );
    182 		if (!pszPasswd && pszRetPasswd) {
    183 			shredPasswd( pszRetPasswd );
    184 			return NULL;
    185 		}
    186 
    187 		// If this is confirmation pass check for match
    188 		if ( pszRetPasswd ) {
    189 			// Matched work complete
    190 			if ( strcmp( pszPasswd, pszRetPasswd ) == 0)
    191 				goto out;
    192 
    193 			// No match clean-up
    194 			logMsg( _("Passwords didn't match\n") );
    195 
    196 			// pszPasswd will be cleaned up at out label
    197 			shredPasswd( pszRetPasswd );
    198 			pszRetPasswd = NULL;
    199 			goto out;
    200 		}
    201 
    202 		// Save this passwd for next pass and/or return val
    203 		pszRetPasswd = strdup( pszPasswd );
    204 		if ( !pszRetPasswd )
    205 			goto out;
    206 
    207 		pszPrompt = _("Confirm password: ");
    208 	} while (a_bConfirm);
    209 
    210 out:
    211 	if (pszRetPasswd) {
    212 		*a_iLen = strlen(pszRetPasswd);
    213 
    214 		if (a_bUseUnicode) {
    215 			shredPasswd(pszRetPasswd);
    216 			pszRetPasswd = (char *)Trspi_Native_To_UNICODE((BYTE *)pszPasswd, (unsigned int *)a_iLen);
    217 		}
    218 	}
    219 
    220 	// pszPasswd is a static buffer, just clear it
    221 	if ( pszPasswd )
    222 		__memset( pszPasswd, 0, strlen( pszPasswd ) );
    223 
    224 	return pszRetPasswd;
    225 }
    226 
    227 /*
    228  * You must free the memory passed back to you when you are finished.
    229  */
    230 char *getReply( const char *a_pszPrompt, int a_iMaxLen ) {
    231 
    232 	char *pszReply  = NULL;
    233 	int   iReplyLen = a_iMaxLen + 2; // Room for newline and trailing zero
    234 
    235 	if ( iReplyLen <= 0 )
    236 		goto out;
    237 
    238 	pszReply = (char *)calloc( iReplyLen, 1 );
    239 	if ( !pszReply )
    240 		goto out;
    241 
    242 	logMsg( "%s", a_pszPrompt );
    243 	pszReply = fgets( pszReply, iReplyLen, stdin );
    244 	if ( !pszReply )
    245 		goto out;
    246 
    247 	// Be certain that a complete line was read
    248 	if ( ( pszReply[ a_iMaxLen ] != '\n' ) && ( pszReply[ a_iMaxLen ] != '\0' ) ) {
    249 		free( pszReply );
    250 		pszReply = NULL;
    251 		goto out;
    252 	}
    253 
    254 	for ( iReplyLen -= 1; iReplyLen >= 0; iReplyLen-- ) {
    255 		if ( pszReply[ iReplyLen ] == '\0' )
    256 			continue;
    257 
    258 		if ( pszReply[ iReplyLen ] == '\n' )
    259 			pszReply[ iReplyLen ] = '\0';
    260 		break;
    261 	}
    262 
    263 out:
    264 	return pszReply;
    265 }
    266