diff --git a/lib/dsmsession.c b/lib/dsmsession.c index 4fefab6..93157a5 100644 --- a/lib/dsmsession.c +++ b/lib/dsmsession.c @@ -6,6 +6,9 @@ #include #include #include +#include +#include +#include #include "dsmrc.h" #include "dsmapitd.h" @@ -72,7 +75,7 @@ int tsm_checkapi(void) { } /* Initialise a session to the TSM server */ -dsUint32_t tsm_initsess(char *options) { +dsUint32_t tsm_initsess(char *options, char *password) { dsInt16_t rc=0; dsUint32_t dsmHandle=0; dsmApiVersionEx applApi; @@ -97,7 +100,7 @@ dsUint32_t tsm_initsess(char *options) { initIn.apiVersionExP = &applApi; initIn.clientNodeNameP = NULL; initIn.clientOwnerNameP = NULL; - initIn.clientPasswordP = NULL; + initIn.clientPasswordP = password; initIn.applicationTypeP = NULL; initIn.configfile = NULL; initIn.options = options; @@ -119,6 +122,7 @@ dsUint32_t tsm_initsess(char *options) { if (rc != DSM_RC_OK) { printf("%s: dsmChangePW() failed %s\n",__func__,tsm_printerr(dsmHandle,rc)); + dsmTerminate(dsmHandle); return 0; } @@ -397,3 +401,171 @@ dsInt16_t tsm_queryfile(dsUint32_t dsmHandle, dsmQueryType qType, tsm_query_call return DSM_RC_OK; } + +/* Signal handler */ +int intrupt = 0; +void Catch(int signo) { + if(signo) {}; /* so compiler won't complain about unused arguments */ + + intrupt = 1; +} + +/* Uses sigaction to establish signal handler */ +int install_sig_handler(int signum, void (*sig_handler)(int)) { + struct sigaction action; + int rc; + + action.sa_handler = sig_handler; /* signal handler function */ + sigemptyset( &action.sa_mask ); /* mask of signals to block */ + + action.sa_flags = SA_NOCLDSTOP; + + rc = sigaction( + signum, /* I */ /* signal identifier */ + &action, /* *I */ /* new action for signal */ + NULL ); /* *O */ /* previous action - not needed */ + + return (rc); +} + +int ReadPass(char *text, char *buffer, int length) { + struct termio ttyState, ttyStateSave; + register char *p; + register int c; + int rc; + FILE *ttyFH; + + struct sigaction action; + + /* Let's flush any prompt to the terminal that may be pending. */ + fflush(stdout); + + /* Open the console input device */ + if((ttyFH = fopen("/dev/tty", "r")) == NULL) + return(-1); + else + setbuf(ttyFH, (char *)NULL); + + /* Reset the interrupt flag */ + intrupt = 0; + + /* Trap the "BREAK" interrupt */ + (void) sigaction( SIGINT, NULL, &action ); /* save current hdlr */ + (void) install_sig_handler( SIGINT, Catch ); /* install new hdlr */ + + /* Get current state */ + rc = ioctl(fileno(ttyFH), TCGETA, &ttyStateSave); + if (rc == -1) + return(-1); + + /* Copy the saved tty state into a work field */ + ttyState = ttyStateSave; + + /* Turn off ECHO */ + ttyState.c_lflag &= ~ECHO; + rc = ioctl(fileno(ttyFH), TCSETA, &ttyState); + if (rc == -1) + return(-1); + + printf(text); + + /* Read the password (quietly) */ + for(p=buffer; !intrupt && (c = getc(ttyFH)) != '\n' && c != EOF; ) { + if(p < buffer+length) + *p++ = c; + } + *p = '\0'; + + printf("\n"); + + /* Restore the tty state settings */ + rc = ioctl(fileno(ttyFH), TCSETA, &ttyStateSave); + if (rc == -1) + return(-1); + + /* Reset the interrupt handler */ + (void) sigaction( SIGINT, &action, NULL ); + + if(ttyFH != stdin) + (void) fclose(ttyFH); + if(intrupt) + (void) kill(getpid(), SIGINT); + + return(strlen(buffer)); +} + +/* + * Set the TSM Node password + * + * We use a callback to process the list, the callback should return: + */ +int tsm_setpassword(char *options) { + uint32 dsmHandle; + bool_t done = bFalse; + uint16 pw_trys = 0; + uint16 len = 0; + char input[INPUTLEN]; + char pw_cur[DSM_MAX_VERIFIER_LENGTH + 1]; + char pw_new [DSM_MAX_VERIFIER_LENGTH + 1]; + + int rc; + + while (!done) { + // Current Password + rc = ReadPass("Enter your current password: ",input,INPUTLEN); + len = strlen(input); + if ((len > DSM_MAX_VERIFIER_LENGTH) || !len || (rc < 0)) { + printf("Current password is invalid. Please try again.\n"); + continue; + } else { + strcpy(pw_cur,input); + } + + // New password + rc = ReadPass("Enter your new password: ",input,INPUTLEN); + len = strlen(input); + if ((len > DSM_MAX_VERIFIER_LENGTH) || !len || (rc < 0)) { + printf("New password is invalid. Please try again.\n"); + continue; + } else { + strcpy(pw_new,input); + } + + // Verify new password + rc = ReadPass("Enter your new password again: ",input,INPUTLEN); + len = strlen(input); + if ((len > DSM_MAX_VERIFIER_LENGTH) || !len || (rc < 0)) { + printf("New password is invalid. Please try again.\n"); + continue; + + } else { + // Compare new pw copies to make sure no typos from user. + if ((strcmp(pw_new,input))) { + pw_trys++; + + if (pw_trys > 3) + debugLog(0,__func__,"ERROR: Passwords dont match, tried too many times.",3); + else + debugLog(0,__func__,"WARN: Your new passwords do not match, please try again...",0); + + } else { + done = bTrue; + } + } + } + + dsmHandle = tsm_initsess(options,pw_cur); + if (! dsmHandle) { + debugLog(0,__func__,"ERROR: Unable to create TSM session with your password.",2); + } + + rc = dsmChangePW(dsmHandle,pw_cur,pw_new); + if (rc) + debugLog(0,__func__,"ERROR: Password change failed.",2); + else + printf("\nYour new password has been accepted and updated.\n"); + + dsmTerminate(dsmHandle); + + return 1; +} diff --git a/tsmpipe.c b/tsmpipe.c index fa20c66..c2d7455 100644 --- a/tsmpipe.c +++ b/tsmpipe.c @@ -69,8 +69,9 @@ void usage(void) { fprintf(stderr, "tsmpipe %s, usage:\n" "\n" - "tsmpipe [-i]|[[-A|-B|-U] [-c|-x|-d|-t] -s fsname -f filepath [-l len] ...]\n" - " -i Show session information:\n" + "tsmpipe [-i|-p]|[[-A|-B|-U] [-c|-x|-d|-t] -s fsname -f filepath [-l len] ...]\n" + " -i Show session information\n" + " -p Set Password\n" " -A, -B and -U are mutually exclusive:\n" " -A Use Archive objects\n" " -B Use Backup objects\n" @@ -102,14 +103,13 @@ void usage(void) { " -V Verbose information on TSM transfer\n" ,_TSMPIPE_VERSION); - exit(1); + exit(0); } void usage_action(void) { - debugLog(0,__func__,"ERROR: Must give one of -i, -c, -x, -d, -t",1); + debugLog(0,__func__,"ERROR: Must give one of -i, -p, -c, -x, -d, -t",1); } - int main(int argc, char *argv[]) { int c; extern int optopt; @@ -130,13 +130,14 @@ int main(int argc, char *argv[]) { char *digest=NULL; #endif - while ((c = getopt(argc, argv, "hiABcxdtUvVe:E:f:Fl:L:m:n:N:s:D:O:P:")) != -1) { + while ((c = getopt(argc, argv, "hiABcxdtUvVe:E:f:Fl:L:m:n:N:s:D:O:pP:")) != -1) { switch(c) { case 'h': usage(); break; case 'A': qType = qtArchive; break; case 'B': qType = qtBackup; break; case 'i': if (action != 0) usage_action(); action = ACTION_INFO; break; + case 'p': if (action != 0) usage_action(); action = ACTION_PASSWORD; break; case 'c': if (action != 0) usage_action(); action = ACTION_CREATE; break; case 'x': if (action != 0) usage_action(); action = ACTION_EXTRACT; break; case 'd': if (action != 0) usage_action(); action = ACTION_DELETE; break; @@ -174,7 +175,18 @@ int main(int argc, char *argv[]) { // Arguement Validation if (action == 0) { - debugLog(0,__func__,"ERROR: Must give one of -i, -c, -x, -d, -t",1); + usage_action(); + } + + if (action == ACTION_PASSWORD) { + rc = tsm_setpassword(options); + + if (! rc) + debugLog(0,__func__,"ERROR: Operation Failed",3); + else + debugLog(1,__func__,"Operation Success",0); + + exit(0); } if (action != ACTION_LIST && friendly) { @@ -222,7 +234,7 @@ int main(int argc, char *argv[]) { // OK, we are ready to talk to TSM debugLog(1,__func__,"Create TSM session",0); - dsmHandle = tsm_initsess(options); + dsmHandle = tsm_initsess(options,NULL); if (! dsmHandle) debugLog(0,__func__,"ERROR: Unable to create TSM session?",2); diff --git a/tsmpipe.h b/tsmpipe.h index 46c4936..6945d40 100644 --- a/tsmpipe.h +++ b/tsmpipe.h @@ -1,4 +1,5 @@ -#define _TSMPIPE_VERSION "1.6.4" +#define _TSMPIPE_VERSION "1.6.5" +#define INPUTLEN 1025 #define ACTION_INFO 1 #define ACTION_CREATE 2 @@ -7,6 +8,7 @@ #define ACTION_LIST 5 #define ACTION_UPDATE 6 #define ACTION_CREATE_UPDATE 7 +#define ACTION_PASSWORD 8 #define DSM_COMM_TCPIP6 6 // There is no DSM_COMM_ const for TCPIPv6 // If you want to use MD5/SHA1 calculations as the data goes in here, ensure this is defined. @@ -26,7 +28,7 @@ extern void debugLog (int level, const char *func, char *message, int die); extern dsmDate dsmStrToDate(char *s); extern dsmObjName dsmNameToObjname(char *fsname, char *filename); extern dsInt16_t tsm_queryfile(dsUint32_t sesshandle, dsmQueryType qType, tsm_query_callback usercb, void *userdata, qryArchiveData qaData, qryBackupData qbData, dsBool_t friendly); -extern dsUint32_t tsm_initsess(char *options); +extern dsUint32_t tsm_initsess(char *options, char *password); extern dsBool_t compressEnabled; extern int tsm_deletefile (dsUint32_t dsmHandle, dsmQueryType qType, qryArchiveData qaData, qryBackupData qbData); @@ -37,6 +39,7 @@ extern double tsm_sendfile (dsUint32_t dsmHandle, char *fsname, char *filename #else extern double tsm_sendfile (dsUint32_t dsmHandle, char *fsname, char *filename, long long length, char *description, dsmSendType sendtype, dsBool_t startstop, dsBoot_t summary); #endif +extern int tsm_setpassword(char *options); extern int tsm_sessioninfo(dsUint32_t dsmHandle); extern int tsm_updatefs(dsUint32_t dsmHandle, char *fsname, long long size); extern int tsm_datefs(dsUint32_t dsmHandle, char *fsname, int startstop);