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 #ifdef __GCC
59 char szShortOpts[strlen( pszGenShortOpts )
60 + ( ( a_pszShortOpts == NULL ) ? 0 : strlen( a_pszShortOpts ) )
61 + 1];
62
63 int iNumGenLongOpts = sizeof( sGenLongOpts ) / sizeof( struct option );
64 struct option sLongOpts[iNumGenLongOpts + a_iNumOpts + 1];
65
66 int iOpt;
67 int rc;
68 #else
69 int iOpt;
70 int rc;
71
72 char *szShortOpts;
73 int iNumShortOpts, iNumGenLongOpts;
74 struct option *sLongOpts;
75
76 iNumShortOpts = strlen( pszGenShortOpts ) +
77 ( ( a_pszShortOpts == NULL ) ? 0 : strlen( a_pszShortOpts ) );
78 iNumGenLongOpts = sizeof( sGenLongOpts ) / sizeof( struct option );
79
80 szShortOpts = malloc(iNumShortOpts + 1);
81 sLongOpts = malloc((iNumGenLongOpts + a_iNumOpts + 1)
82 * sizeof(struct option));
83 if( (szShortOpts == NULL) || (sLongOpts == NULL) ) {
84 perror("malloc");
85 return -1;
86 }
87 #endif
88 strcpy( szShortOpts, pszGenShortOpts);
89 if ( a_pszShortOpts )
90 strcat( szShortOpts, a_pszShortOpts );
91
92 #ifdef __GCC
93 __memset( sLongOpts, 0, sizeof( sLongOpts ) );
94 #else
95 __memset( sLongOpts, 0, (iNumGenLongOpts + a_iNumOpts + 1) * sizeof(struct option));
96 #endif
97 memcpy( sLongOpts, sGenLongOpts, sizeof( sGenLongOpts ) );
98 if ( a_sLongOpts ) {
99 memcpy( sLongOpts + iNumGenLongOpts,
100 a_sLongOpts,
101 a_iNumOpts * sizeof( struct option ) );
102 }
103
104 while ( ( iOpt = getopt_long( a_iNumArgs, a_pszArgs,
105 szShortOpts, sLongOpts, NULL ) ) != -1 ) {
106
107 switch ( iOpt ) {
108 case 'h':
109 tCmdHelp( a_pszArgs[0] );
110 return -1;
111
112 case 'v':
113 logMsg( _("%s version: %s\n"), a_pszArgs[0], CMD_VERSION );
114 return -1;
115
116 case 'l':
117 if ( !optarg ) {
118 tCmdHelp( a_pszArgs[0] );
119 return -1;
120 }
121
122 if ( strcmp( optarg, LOG_NONE ) == 0 )
123 iLogLevel = LOG_LEVEL_NONE;
124 else if ( strcmp( optarg, LOG_ERROR ) == 0 )
125 iLogLevel = LOG_LEVEL_ERROR;
126 else if ( strcmp( optarg, LOG_INFO ) == 0 )
127 iLogLevel = LOG_LEVEL_INFO;
128 else if ( strcmp( optarg, LOG_DEBUG ) == 0 )
129 iLogLevel = LOG_LEVEL_DEBUG;
130 else {
131 logMsg( _("Valid log levels are: %s, %s, %s, %s\n"),
132 LOG_NONE,
133 LOG_ERROR,
134 LOG_INFO,
135 LOG_DEBUG );
136 tCmdHelp( a_pszArgs[0] );
137 return -1;
138 }
139 break;
140 case 'u':
141 useUnicode = TRUE;
142 break;
143 case '?':
144 tCmdHelp( a_pszArgs[0] );
145 return -1;
146
147 default:
148 if ( !a_tCmdOptParser )
149 return -1;
150
151 rc = a_tCmdOptParser( iOpt, optarg );
152 if ( rc != 0 )
153 return rc;
154 break;
155 }
156 }
157
158 return 0;
159 }
160
161 void * __no_optimize
__memset(void * s,int c,size_t n)162 __memset(void *s, int c, size_t n)
163 {
164 return memset(s, c, n);
165 }
166
167 /*
168 * This function should be called when you are done with a password
169 * the above getPasswd function to properly clean up.
170 */
shredPasswd(char * a_pszPasswd)171 void shredPasswd( char *a_pszPasswd ) {
172
173 if ( a_pszPasswd ) {
174 __memset( a_pszPasswd, 0, strlen( a_pszPasswd ) );
175 free( a_pszPasswd );
176 }
177 }
178
179 /*
180 * You must free the memory passed back to you when you are finished.
181 * Loop will always terminate by the second pass.
182 * Safest use of getpass is to zero the memory as soon as possible.
183 */
getPlainPasswd(const char * a_pszPrompt,BOOL a_bConfirm)184 char *getPlainPasswd(const char *a_pszPrompt, BOOL a_bConfirm) {
185 int len;
186 return _getPasswd(a_pszPrompt, &len, a_bConfirm, FALSE);
187 }
188
189 #ifndef TSS_LIB_IS_12
getPasswd(const char * a_pszPrompt,int * a_iLen,BOOL a_bConfirm)190 char *getPasswd(const char *a_pszPrompt, int* a_iLen,
191 BOOL a_bConfirm) {
192 return _getPasswd( a_pszPrompt, a_iLen, a_bConfirm, useUnicode);
193 }
194 #endif
_getPasswd(const char * a_pszPrompt,int * a_iLen,BOOL a_bConfirm,BOOL a_bUseUnicode)195 char *_getPasswd(const char *a_pszPrompt, int* a_iLen,
196 BOOL a_bConfirm, BOOL a_bUseUnicode) {
197
198 char *pszPrompt = (char *)a_pszPrompt;
199 char *pszPasswd = NULL;
200 char *pszRetPasswd = NULL;
201
202 do {
203 // Get password value from user - this is a static buffer
204 // and should never be freed
205 pszPasswd = getpass( pszPrompt );
206 if (!pszPasswd && pszRetPasswd) {
207 shredPasswd( pszRetPasswd );
208 return NULL;
209 }
210
211 // If this is confirmation pass check for match
212 if ( pszRetPasswd ) {
213 // Matched work complete
214 if ( strcmp( pszPasswd, pszRetPasswd ) == 0)
215 goto out;
216
217 // No match clean-up
218 logMsg( _("Passwords didn't match\n") );
219
220 // pszPasswd will be cleaned up at out label
221 shredPasswd( pszRetPasswd );
222 pszRetPasswd = NULL;
223 goto out;
224 }
225
226 // Save this passwd for next pass and/or return val
227 pszRetPasswd = strdup( pszPasswd );
228 if ( !pszRetPasswd )
229 goto out;
230
231 pszPrompt = _("Confirm password: ");
232 } while (a_bConfirm);
233
234 out:
235 if (pszRetPasswd) {
236 *a_iLen = strlen(pszRetPasswd);
237
238 if (a_bUseUnicode) {
239 shredPasswd(pszRetPasswd);
240 pszRetPasswd = (char *)Trspi_Native_To_UNICODE((BYTE *)pszPasswd, (unsigned int *)a_iLen);
241 }
242 }
243
244 // pszPasswd is a static buffer, just clear it
245 if ( pszPasswd )
246 __memset( pszPasswd, 0, strlen( pszPasswd ) );
247
248 return pszRetPasswd;
249 }
250
251 /*
252 * You must free the memory passed back to you when you are finished.
253 */
getReply(const char * a_pszPrompt,int a_iMaxLen)254 char *getReply( const char *a_pszPrompt, int a_iMaxLen ) {
255
256 char *pszReply = NULL;
257 int iReplyLen = a_iMaxLen + 2; // Room for newline and trailing zero
258
259 if ( iReplyLen <= 0 )
260 goto out;
261
262 pszReply = (char *)calloc( iReplyLen, 1 );
263 if ( !pszReply )
264 goto out;
265
266 logMsg( "%s", a_pszPrompt );
267 pszReply = fgets( pszReply, iReplyLen, stdin );
268 if ( !pszReply )
269 goto out;
270
271 // Be certain that a complete line was read
272 if ( ( pszReply[ a_iMaxLen ] != '\n' ) && ( pszReply[ a_iMaxLen ] != '\0' ) ) {
273 free( pszReply );
274 pszReply = NULL;
275 goto out;
276 }
277
278 for ( iReplyLen -= 1; iReplyLen >= 0; iReplyLen-- ) {
279 if ( pszReply[ iReplyLen ] == '\0' )
280 continue;
281
282 if ( pszReply[ iReplyLen ] == '\n' )
283 pszReply[ iReplyLen ] = '\0';
284 break;
285 }
286
287 out:
288 return pszReply;
289 }
290