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