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
initIntlSys()42 void initIntlSys( ) {
43
44 setlocale( LC_ALL, "" );
45 bindtextdomain( PACKAGE, LOCALEDIR );
46 textdomain( PACKAGE );
47 }
48
49 int
genericOptHandler(int a_iNumArgs,char ** a_pszArgs,const char * a_pszShortOpts,struct option * a_sLongOpts,int a_iNumOpts,CmdOptParser a_tCmdOptParser,CmdHelpFunction a_tCmdHelpFunction)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
__memset(void * s,int c,size_t n)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 */
shredPasswd(char * a_pszPasswd)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 */
getPlainPasswd(const char * a_pszPrompt,BOOL a_bConfirm)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
getPasswd(const char * a_pszPrompt,int * a_iLen,BOOL a_bConfirm)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
_getPasswd(const char * a_pszPrompt,int * a_iLen,BOOL a_bConfirm,BOOL a_bUseUnicode)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 */
getReply(const char * a_pszPrompt,int a_iMaxLen)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