irods  4.2.8
About: iRODS (the integrated Rule Oriented Data System) is a distributed data-management system for creating data grids, digital libraries, persistent archives, and real-time data systems.
  Fossies Dox: irods-4.2.8.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

obf.cpp
Go to the documentation of this file.
1 
3 /*
4  These routines obfuscate (scramble or sort-of encrypt) passwords.
5 
6  These are used to avoid storing plain-text passwords in the files,
7  yet still allow automatic authentication. This is better than
8  plain-text passwords sitting around in files and often being
9  transmitted on networks in NFS packets. But, of course, this isn't
10  highly secure, particularly since with this source file one can
11  defeat it. But it does stop attackers from finding passwords by
12  just searching directories.
13 
14  Externally callable routines begin with "obf" and internal routines
15  begin with "obfi".
16 
17  A timestamp is used with this, which will be gotten from the modify
18  time of the authentication file. This way, a simple copy of the
19  file will not successfully authenticate.
20 
21  The UID of the running process is also used in the algorithm.
22 
23  The same password is obfuscated differently (usually), each time the
24  obfuscation is done, so that one will usually be unable to tell by
25  looking at the ciphertext whether two passwords are the same or not.
26  Also, this makes it more difficult to determine the obfuscation
27  algorithm.
28 
29  When the iRODS commands authenticate, they first check if this is
30  available, and use that if possible. Otherwise, they prompt for the
31  password.
32 
33  Returns codes of 0 indicate success, others are iRODS error codes.
34 */
35 
36 
37 #include <stdio.h>
38 #include <openssl/md5.h>
39 #include <openssl/sha.h>
40 #ifndef windows_platform
41 #include <sys/types.h>
42 #include <sys/time.h>
43 #include <sys/timeb.h>
44 #include <fcntl.h>
45 #include <sys/stat.h>
46 #include <string.h>
47 #include <termios.h>
48 #include "termiosUtil.hpp"
49 #endif
50 #include <cstdlib>
51 
52 #include "rods.h"
53 #include "rodsPath.h"
54 #include "authenticate.h"
55 
56 #ifdef _WIN32
57 #include "Unix2Nt.hpp" /* May need something like this for Windows */
58 #include "iRODSNtUtil.hpp" /* May need something like this for Windows */
59 #include "rcGlobalExtern.h"
60 #endif
61 
62 #include <boost/filesystem.hpp>
63 #include <boost/system/error_code.hpp>
64 #include <boost/filesystem/operations.hpp>
65 #include <boost/filesystem/convenience.hpp>
66 #define TMP_FLAG "%TEMPORARY_PW%"
67 
68 #define AUTH_FILENAME_DEFAULT ".irods/.irodsA" /* under the HOME dir */
69 
70 int obfDebug = 0;
71 int timeVal = 0;
72 int isTemp = 0;
73 int doTemp = 0;
74 
76 
77 /* For now, edit this to change the default hash type, types are
78  HASH_TYPE_MD5 and HASH_TYPE_SHA1 */
80 
81 /*
82  What can be a main routine for some simple tests.
83  */
84 int
85 obftestmain( int argc, char *argv[] ) {
86  char p3[MAX_PASSWORD_LEN];
87  int i;
88 
89  obfDebug = 2;
90 
91  if ( argc < 2 ) {
92  printf( "Usage: -d|-e\n" );
93  exit( -1 );
94  }
95 
96  if ( strcmp( argv[1], "-d" ) == 0 ) {
97  i = obfGetPw( p3 );
98  if ( obfDebug ) {
99  printf( "val = %d \n", i );
100  }
101  }
102 
103  if ( strcmp( argv[1], "-e" ) == 0 ) {
104  i = obfSavePw( 1, 0, 1, "" );
105  if ( obfDebug ) {
106  printf( "val = %d \n", i );
107  }
108  }
109  return 0;
110 }
111 
112 int
113 obfSetDebug( int opt ) {
114  obfDebug = opt;
115  return 0;
116 }
117 
118 int
119 obfiGetFilename( char *fileName ) {
120  char *envVar = NULL;
121 
122  envVar = getRodsEnvAuthFileName();
123  if ( envVar != NULL && *envVar != '\0' ) {
124  strcpy( fileName, envVar );
125  return 0;
126  }
127 
128 #ifdef windows_platform
129  if ( ProcessType != CLIENT_PT ) {
130  char *tmpstr1;
131  int t;
132  tmpstr1 = iRODSNtGetServerConfigPath();
133  sprintf( fileName, "%s\\irodsA.txt", tmpstr1 );
134  return 0;
135  }
136 
137  /* for clients */
138  envVar = iRODSNt_gethome();
139 #else
140  envVar = getenv( "HOME" );
141 #endif
142  if ( envVar == NULL ) {
144  }
145  strncpy( fileName, envVar, MAX_NAME_LEN );
146  strncat( fileName, "/", MAX_NAME_LEN );
147  strncat( fileName, AUTH_FILENAME_DEFAULT, MAX_NAME_LEN );
148 
149 #ifdef windows_platform
150  if ( envVar != NULL ) {
151  free( envVar );
152  }
153 #endif
154 
155  return 0;
156 }
157 
158 int
159 obfGetPw( char *pw ) {
160  char myPw[MAX_PASSWORD_LEN + 10];
161  char myPwD[MAX_PASSWORD_LEN + 10];
162  char fileName[MAX_NAME_LEN + 10];
163  char *cp;
164 
165  int i;
166  int envVal;
167 
168  strcpy( pw, "" );
169 
170  envVal = obfiGetEnvKey();
171 
172  i = obfiGetFilename( fileName );
173  if ( i < 0 ) {
174  return i;
175  }
176 
177  i = obfiGetTv( fileName );
178  if ( i < 0 ) {
179  return i;
180  }
181 
182  i = obfiGetPw( fileName, myPw );
183  if ( i < 0 ) {
184  return i;
185  }
186 
187  i = obfiDecode( myPw, myPwD, envVal );
188  if ( i < 0 ) {
189  return i;
190  }
191 
192  isTemp = 0;
193  cp = strstr( myPwD, TMP_FLAG );
194  if ( cp != 0 ) {
195  isTemp = 1;
196  *cp = '\0';
197  }
198 
199  if ( obfDebug ) {
200  printf( "out:%s\n", myPwD );
201  }
202  strcpy( pw, myPwD );
203 
204  return 0;
205 }
206 
207 /*
208  remove the password file
209  opt: if non-zero, don't ask and don't print error;just remove it if it exists.
210 */
211 int
212 obfRmPw( int opt ) {
213  char fileName[MAX_NAME_LEN + 10];
214  char inbuf[MAX_NAME_LEN + 10];
215 
216  if ( int status = obfiGetFilename( fileName ) ) {
217  return status;
218  }
219  boost::filesystem::path filePath( fileName );
220  if ( !boost::filesystem::exists( filePath ) ) {
221  if ( opt == 0 ) {
222  printf( "%s does not exist\n", fileName );
223  }
225  }
226  if ( opt == 0 ) {
227  printf( "Remove %s?:", fileName );
228  const char *fgets_ret = fgets( inbuf, MAX_NAME_LEN, stdin );
229  if ( fgets_ret == NULL || strlen( inbuf ) < 1 || inbuf[0] != 'y' ) {
230  return 0;
231  }
232  }
233  boost::system::error_code error;
234  boost::filesystem::remove( filePath, error );
235  if ( error.value() ) {
236  return UNLINK_FAILED;
237  }
238  return 0;
239 }
240 
241 /* Set timeVal from a fstat of the file after writing to it.
242  Could just use system time, but if it's way off from the file
243  system (NFS on a VM host, for example), it would fail. */
244 int
246 #ifndef windows_platform
247  struct stat statBuf;
248 #else
249  struct irodsntstat statBuf;
250 #endif
251  int wval, fval, lval;
252  wval = write( fd, " ", 1 );
253  if ( wval != 1 ) {
254  return FILE_WRITE_ERR;
255  }
256 #ifndef windows_platform
257  fval = fstat( fd, &statBuf );
258 #else
259  fval = _fstat64( fd, &statBuf );
260 #endif
261  if ( fval < 0 ) {
262  timeVal = 0;
263  return UNABLE_TO_STAT_FILE;
264  }
265  lval = lseek( fd, 0, SEEK_SET );
266  if ( lval < 0 ) {
267  return UNABLE_TO_STAT_FILE;
268  }
269 
270  timeVal = statBuf.st_mtime & 0xffff; /* keep it bounded */
271  return 0;
272 }
273 
274 
275 
276 /* int promptOpt; if 1, echo password as typed, else no echo */
277 /* int fileOpt; if 1, ask permission before writing file */
278 /* int printOpt; if 1, display an updated file msg on success */
279 /* char *pwArg; if non-0-length, this is the new password */
280 int
281 obfSavePw( int promptOpt, int fileOpt, int printOpt, const char *pwArg ) {
282  using namespace boost::filesystem;
283  char fileName[MAX_NAME_LEN + 10];
284  char inbuf[MAX_PASSWORD_LEN + 100];
285  char myPw[MAX_PASSWORD_LEN + 10];
286  int i = 0, fd = 0, envVal = 0;
287 
288  i = obfiGetFilename( fileName );
289  if ( i != 0 ) {
290  return i;
291  }
292 
293  envVal = obfiGetEnvKey();
294 
295  if ( pwArg == NULL || strlen( pwArg ) == 0 ) {
296 #ifdef windows_platform
297  iRODSNtGetUserPasswdInputInConsole( inbuf, "Enter your current iRODS password:", promptOpt );
298 #else
299  irods::termiosUtil tiosutl(STDIN_FILENO);
300  if ( promptOpt != 1 ) {
301  if ( !tiosutl.echoOff() )
302  {
303  printf( "WARNING: Error %d disabling echo mode. Password will be displayed in plaintext.\n", tiosutl.getError() );
304  }
305  }
306 
307  printf( "Enter your current iRODS password:" );
308  const char *fgets_return = fgets( inbuf, MAX_PASSWORD_LEN + 50, stdin );
309 
310  if ( promptOpt != 1 ) {
311  printf( "\n" );
312  if( tiosutl.getValid() && !tiosutl.echoOn() )
313  {
314  printf( "Error reinstating echo mode.\n" );
315  }
316  }
317  if (fgets_return != inbuf || strlen(inbuf) < 2)
318  {
319  // Either error or end-of-file encountered.
320  // If anything was actually entered, the length
321  // will be 2 - to include the '\n'.
322  return NO_PASSWORD_ENTERED;
323  }
324 #endif
325 
326  }
327  else {
328  strncpy( inbuf, pwArg, MAX_PASSWORD_LEN );
329  }
330  i = strlen( inbuf );
331  if ( i < 1 ) {
332  return NO_PASSWORD_ENTERED;
333  }
334  if ( strlen( inbuf ) > MAX_PASSWORD_LEN - 8 ) {
336  }
337  if ( inbuf[i - 1] == '\n' ) {
338  inbuf[i - 1] = '\0'; /* remove trailing \n */
339  }
340 
341  if ( doTemp ) {
342  strcat( inbuf, TMP_FLAG );
343  }
344 
345  fd = obfiOpenOutFile( fileName, fileOpt );
346  if ( fd < 0 ) {
347  return FILE_OPEN_ERR;
348  }
349 
350  if ( fd == 0 ) {
351  return ( 0 ); /* user canceled */
352  }
353 
354  i = obfiSetTimeFromFile( fd );
355  if ( i < 0 ) {
356  close( fd );
357  return i;
358  }
359 
360  obfiEncode( inbuf, myPw, envVal );
361  if ( obfDebug > 1 ) {
362  printf( " in:%s out:%s\n", inbuf, myPw );
363  }
364 
365  i = obfiWritePw( fd, myPw );
366  close( fd );
367  if ( i < 0 ) {
368  return i;
369  }
370 
371  if ( obfDebug || printOpt ) {
372  printf( "Successfully wrote %s\n", fileName );
373  }
374 
375  return 0;
376 }
377 
378 /* various options for temporary auth files/pws */
379 int obfTempOps( int tmpOpt ) {
380  char fileName[MAX_NAME_LEN + 10];
381  char pw[MAX_PASSWORD_LEN + 10];
382  int i;
383  if ( tmpOpt == 1 ) { /* store pw flagged as temporary */
384  doTemp = 1;
385  }
386 
387  if ( tmpOpt == 2 ) { /* remove the pw file if temporary */
388  i = obfGetPw( pw );
389  strcpy( pw, " " );
390  if ( i != 0 ) {
391  return i;
392  }
393  if ( isTemp ) {
394  i = obfiGetFilename( fileName );
395  if ( i != 0 ) {
396  return i;
397  }
398  unlink( fileName );
399  }
400  }
401  return 0;
402 }
403 
404 int
405 obfiGetTv( char *fileName ) {
406 #ifndef windows_platform
407  struct stat statBuf;
408 #else
409  struct irodsntstat statBuf;
410 #endif
411  int fval;
412 
413 #ifndef windows_platform
414  fval = stat( fileName, &statBuf );
415 #else
416  fval = iRODSNt_stat( fileName, &statBuf );
417 #endif
418 
419  if ( fval < 0 ) {
420  timeVal = 0;
421  return UNABLE_TO_STAT_FILE;
422  }
423 
424  timeVal = statBuf.st_mtime & 0xffff; /* keep it bounded */
425  return 0;
426 }
427 
428 int
429 obfiGetPw( const char *fileName, char *pw ) {
430 #ifdef windows_platform
431  int fd_in = iRODSNt_open( fileName, O_RDONLY, 1 );
432 #else
433  int fd_in = open( fileName, O_RDONLY, 0 );
434 #endif
435 
436  if ( fd_in < 0 ) {
437  return FILE_OPEN_ERR;
438  }
439 
440  char buf[MAX_PASSWORD_LEN + 1];
441  int rval = read( fd_in, buf, MAX_PASSWORD_LEN );
442  close( fd_in );
443 
444  if ( rval < 0 ) {
445  return FILE_READ_ERR;
446  }
447  buf[rval] = '\0';
448  if ( strlen( buf ) >= MAX_PASSWORD_LEN ) {
450  }
451 
452  snprintf( pw, MAX_PASSWORD_LEN, "%s", buf );
453  return 0;
454 }
455 
456 int
457 obfiOpenOutFile( const char *fileName, int fileOpt ) {
458  char inbuf[MAX_NAME_LEN] = "";
459  int i = 0, fd_out = 0;
460 
461 #ifdef _WIN32
462  fd_out = iRODSNt_open( fileName, O_CREAT | O_WRONLY | O_EXCL, 1 );
463 #else
464  fd_out = open( fileName, O_CREAT | O_WRONLY | O_EXCL, 0600 );
465 #endif
466 
467  if ( fd_out < 0 ) {
468  if ( errno != EEXIST ) {
469  return FILE_OPEN_ERR;
470  }
471  if ( fileOpt > 0 ) {
472  printf( "Overwrite '%s'?:", fileName );
473  if ( NULL == fgets( inbuf, MAX_NAME_LEN, stdin ) ) {
474  // end of line reached or no input
475  }
476  i = strlen( inbuf );
477  if ( i < 2 ) {
478  return 0;
479  }
480  }
481  else {
482  strcpy( inbuf, "y" );
483  }
484  if ( inbuf[0] == 'y' ) {
485 #ifdef windows_platform
486  fd_out = iRODSNt_open( fileName, O_CREAT | O_WRONLY | O_TRUNC, 1 );
487 #else
488  fd_out = open( fileName, O_CREAT | O_WRONLY | O_TRUNC, 0600 );
489 #endif
490  if ( fd_out < 0 ) {
491  return FILE_OPEN_ERR;
492  }
493  }
494  else {
495  return 0;
496  }
497  }
498  return fd_out;
499 }
500 
501 int
502 obfiWritePw( int fd, const char *pw ) {
503  int wval, len;
504  len = strlen( pw );
505  wval = write( fd, pw, len + 1 );
506  if ( wval != len + 1 ) {
507  return FILE_WRITE_ERR;
508  }
509  return 0;
510 }
511 
512 int obfiTimeval() {
513  long sec;
514  int val;
515 
516  struct timeval nowtime;
517 
518  ( void )gettimeofday( &nowtime, ( struct timezone * )0 );
519  sec = nowtime.tv_sec;
520 
521  val = sec;
522  val = val & 0xffff; /* keep it bounded */
523  if ( obfDebug > 1 ) {
524  printf( "val = %d %x\n", val, val );
525  }
526  return val;
527 }
528 
529 
530 /*
531  Obfuscate a password
532 */
533 void
534 obfiEncode( const char *in, char *out, int extra ) {
535  int i;
536  long seq;
537  const char *my_in;
538 
539  /* struct timeb timeb_time; */
540  struct timeval nowtime;
541 
542  int rval;
543  int wheel_len;
544  int wheel[26 + 26 + 10 + 15];
545  int j, addin, addin_i, found;
546  int ii;
547  int now;
548  char headstring[10];
549 #ifndef _WIN32
550  int uid;
551 #endif
552  /*
553  Set up an array of characters that we will transpose.
554  */
555 
556  wheel_len = 26 + 26 + 10 + 15;
557  j = 0;
558  for ( i = 0; i < 10; i++ ) {
559  wheel[j++] = ( int )'0' + i;
560  }
561  for ( i = 0; i < 26; i++ ) {
562  wheel[j++] = ( int )'A' + i;
563  }
564  for ( i = 0; i < 26; i++ ) {
565  wheel[j++] = ( int )'a' + i;
566  }
567  for ( i = 0; i < 15; i++ ) {
568  wheel[j++] = ( int )'!' + i;
569  }
570 
571  /*
572  get uid to use as part of the key
573  */
574 #ifndef _WIN32
575  uid = getuid();
576  uid = uid & 0xf5f; /* keep it fairly small and not exactly uid */
577 #endif
578 
579  /*
580  get a pseudo random number
581  */
582 
583  ( void )gettimeofday( &nowtime, ( struct timezone * )0 );
584  rval = nowtime.tv_usec & 0xf;
585 
586  /*
587  and use it to pick a pattern for ascii offsets
588  */
589  seq = 0;
590  if ( rval == 0 ) {
591  seq = 0xd768b678;
592  }
593  if ( rval == 1 ) {
594  seq = 0xedfdaf56;
595  }
596  if ( rval == 2 ) {
597  seq = 0x2420231b;
598  }
599  if ( rval == 3 ) {
600  seq = 0x987098d8;
601  }
602  if ( rval == 4 ) {
603  seq = 0xc1bdfeee;
604  }
605  if ( rval == 5 ) {
606  seq = 0xf572341f;
607  }
608  if ( rval == 6 ) {
609  seq = 0x478def3a;
610  }
611  if ( rval == 7 ) {
612  seq = 0xa830d343;
613  }
614  if ( rval == 8 ) {
615  seq = 0x774dfa2a;
616  }
617  if ( rval == 9 ) {
618  seq = 0x6720731e;
619  }
620  if ( rval == 10 ) {
621  seq = 0x346fa320;
622  }
623  if ( rval == 11 ) {
624  seq = 0x6ffdf43a;
625  }
626  if ( rval == 12 ) {
627  seq = 0x7723a320;
628  }
629  if ( rval == 13 ) {
630  seq = 0xdf67d02e;
631  }
632  if ( rval == 14 ) {
633  seq = 0x86ad240a;
634  }
635  if ( rval == 15 ) {
636  seq = 0xe76d342e;
637  }
638 
639  /*
640  get the timestamp and other id
641  */
642  if ( timeVal != 0 ) {
643  now = timeVal; /* from file, normally */
644  }
645  else {
646  now = obfiTimeval();
647  }
648  headstring[1] = ( ( now >> 4 ) & 0xf ) + 'a';
649  headstring[2] = ( now & 0xf ) + 'a';
650  headstring[3] = ( ( now >> 12 ) & 0xf ) + 'a';
651  headstring[4] = ( ( now >> 8 ) & 0xf ) + 'a';
652  headstring[5] = '\0';
653  headstring[0] = 'S' - ( ( rval & 0x7 ) * 2 ); /* another check value */
654 
655  *out++ = '.'; /* store our initial, human-readable identifier */
656 
657  addin_i = 0;
658  my_in = headstring; /* start with head string */
659  for ( ii = 0;; ) {
660  ii++;
661  if ( ii == 6 ) {
662  *out++ = rval + 'e'; /* store the key */
663  my_in = in; /* now start using the input string */
664  }
665  found = 0;
666  addin = ( seq >> addin_i ) & 0x1f;
667  addin += extra;
668 #ifndef _WIN32
669  addin += uid;
670  addin_i += 3;
671 #else
672  addin_i += 2;
673 #endif
674  if ( addin_i > 28 ) {
675  addin_i = 0;
676  }
677  for ( i = 0; i < wheel_len; i++ ) {
678  if ( *my_in == ( char )wheel[i] ) {
679  j = i + addin;
680  if ( obfDebug > 1 ) {
681  printf( "j1=%d ", j );
682  }
683  j = j % wheel_len;
684  if ( obfDebug > 1 ) {
685  printf( "j2=%d \n", j );
686  }
687  *out++ = ( char )wheel[j];
688  found = 1;
689  break;
690  }
691  }
692  if ( found == 0 ) {
693  if ( *my_in == '\0' ) {
694  *out++ = '\0';
695  return;
696  }
697  else {
698  *out++ = *my_in;
699  }
700  }
701  my_in++;
702  }
703 }
704 
705 
706 int
707 obfiTimeCheck( int time1, int time2 ) {
708  int fudge = 20;
709  int delta;
710 
711  /* printf("time1=%d time2=%d\n",time1, time2); */
712 
713  delta = time1 - time2;
714  if ( delta < 0 ) {
715  delta = 0 - delta;
716  }
717  if ( delta < fudge ) {
718  return 0;
719  }
720 
721  if ( time1 < 65000 ) {
722  time1 += 65535;
723  }
724  if ( time2 < 65000 ) {
725  time2 += 65535;
726  }
727 
728  delta = time1 - time2;
729  if ( delta < 0 ) {
730  delta = 0 - delta;
731  }
732  if ( delta < fudge ) {
733  return 0;
734  }
735 
736  return 1;
737 }
738 
739 
740 
741 int
742 obfiDecode( const char *in, char *out, int extra ) {
743  int i;
744  long seq;
745  const char *p1;
746 
747  int rval;
748  int wheel_len;
749  int wheel[26 + 26 + 10 + 15];
750  int j, addin, addin_i, kpos, found, nout = 0;
751  char headstring[10];
752  int ii, too_short;
753  char *my_out;
754  const char* my_in;
755  int not_en, encodedTime;
756 #ifndef _WIN32
757  int uid;
758 #endif
759 
760  wheel_len = 26 + 26 + 10 + 15;
761 
762  /*
763  get uid to use as part of the key
764  */
765 #ifndef _WIN32
766  uid = getuid();
767  uid = uid & 0xf5f; /* keep it fairly small and not exactly uid */
768 #endif
769 
770  /*
771  Set up an array of characters that we will transpose.
772  */
773  j = 0;
774  for ( i = 0; i < 10; i++ ) {
775  wheel[j++] = ( int )'0' + i;
776  }
777  for ( i = 0; i < 26; i++ ) {
778  wheel[j++] = ( int )'A' + i;
779  }
780  for ( i = 0; i < 26; i++ ) {
781  wheel[j++] = ( int )'a' + i;
782  }
783  for ( i = 0; i < 15; i++ ) {
784  wheel[j++] = ( int )'!' + i;
785  }
786 
787  too_short = 0;
788  for ( p1 = in, i = 0; i < 6; i++ ) {
789  if ( *p1++ == '\0' ) {
790  too_short = 1;
791  }
792  }
793 
794  kpos = 6;
795  p1 = in;
796  for ( i = 0; i < kpos; i++, p1++ ) {
797  ;
798  }
799  rval = ( int ) * p1;
800  rval = rval - 'e';
801 
802  if ( rval > 15 || rval < 0 || too_short == 1 ) { /* invalid key or too short */
803  while ( ( *out++ = *in++ ) != '\0' ) {
804  ; /* return input string */
805  }
807  }
808 
809  seq = 0;
810  if ( rval == 0 ) {
811  seq = 0xd768b678;
812  }
813  if ( rval == 1 ) {
814  seq = 0xedfdaf56;
815  }
816  if ( rval == 2 ) {
817  seq = 0x2420231b;
818  }
819  if ( rval == 3 ) {
820  seq = 0x987098d8;
821  }
822  if ( rval == 4 ) {
823  seq = 0xc1bdfeee;
824  }
825  if ( rval == 5 ) {
826  seq = 0xf572341f;
827  }
828  if ( rval == 6 ) {
829  seq = 0x478def3a;
830  }
831  if ( rval == 7 ) {
832  seq = 0xa830d343;
833  }
834  if ( rval == 8 ) {
835  seq = 0x774dfa2a;
836  }
837  if ( rval == 9 ) {
838  seq = 0x6720731e;
839  }
840  if ( rval == 10 ) {
841  seq = 0x346fa320;
842  }
843  if ( rval == 11 ) {
844  seq = 0x6ffdf43a;
845  }
846  if ( rval == 12 ) {
847  seq = 0x7723a320;
848  }
849  if ( rval == 13 ) {
850  seq = 0xdf67d02e;
851  }
852  if ( rval == 14 ) {
853  seq = 0x86ad240a;
854  }
855  if ( rval == 15 ) {
856  seq = 0xe76d342e;
857  }
858 
859  addin_i = 0;
860  my_out = headstring;
861  my_in = in;
862  my_in++; /* skip leading '.' */
863  for ( ii = 0;; ) {
864  ii++;
865  if ( ii == 6 ) {
866  not_en = 0;
867  if ( *in != '.' ) {
868  not_en = 1; /* is not 'encrypted' */
869  }
870  if ( headstring[0] != 'S' - ( ( rval & 0x7 ) * 2 ) ) {
871  not_en = 1;
872  if ( obfDebug ) {
873  printf( "not s\n" );
874  }
875  }
876 
877  encodedTime = ( ( headstring[1] - 'a' ) << 4 ) + ( headstring[2] - 'a' ) +
878  ( ( headstring[3] - 'a' ) << 12 ) + ( ( headstring[4] - 'a' ) << 8 );
879 
880 #ifndef _WIN32
881  if ( obfiTimeCheck( encodedTime, timeVal ) ) {
882  not_en = 1;
883  }
884 #else /* The file always contains an encrypted password in Windows. */
885  not_en = 0;
886 #endif
887 
888  if ( obfDebug ) {
889  printf( "timeVal=%d encodedTime=%d\n", timeVal, encodedTime );
890  }
891 
892  my_out = out; /* start outputing for real */
893  if ( not_en == 1 ) {
894  while ( ( *out++ = *in++ ) != '\0' ) {
895  ; /* return input string */
896  }
898  }
899  my_in++; /* skip key */
900  }
901  else {
902  found = 0;
903  addin = ( seq >> addin_i ) & 0x1f;
904  addin += extra;
905 #ifndef _WIN32
906  addin += uid;
907  addin_i += 3;
908 #else
909  addin_i += 2;
910 #endif
911  if ( addin_i > 28 ) {
912  addin_i = 0;
913  }
914  for ( i = 0; i < wheel_len; i++ ) {
915  if ( *my_in == ( char )wheel[i] ) {
916  j = i - addin;
917  if ( obfDebug ) {
918  printf( "j=%d ", j );
919  }
920 
921  while ( j < 0 ) {
922  j += wheel_len;
923  }
924  if ( obfDebug ) {
925  printf( "j2=%d \n", j );
926  }
927 
928  *my_out++ = ( char )wheel[j];
929  nout++;
930  found = 1;
931  break;
932  }
933  }
934  if ( found == 0 ) {
935  if ( *my_in == '\0' ) {
936  *my_out++ = '\0';
937  return 0;
938  }
939  else {
940  *my_out++ = *my_in;
941  nout++;
942  }
943  }
944  my_in++;
945  }
946  }
947 }
948 
949 int
951  /* May want to do this someday, but at least not for now */
952  return 0;
953 }
954 
955 void
958  if ( obfDebug ) {
959  printf( "hashType now %d\n", defaultHashType );
960  }
961 }
962 
963 int
965  return defaultHashType;
966 }
967 
968 /* Generate a hash string using MD5 or Sha1 */
969 void
970 obfMakeOneWayHash( int hashType,
971  unsigned const char *inBuf, int inBufSize, unsigned char *outHash ) {
972 
973  MD5_CTX md5Context;
974  SHA_CTX shaContext;
975 
976  static char outBuf[50];
977 
978  if ( hashType == HASH_TYPE_SHA1 ||
979  ( hashType == HASH_TYPE_DEFAULT && defaultHashType == HASH_TYPE_SHA1 ) ) {
980  if ( obfDebug ) {
981  printf( "obfMakeOneWayHash sha1\n" );
982  }
983  SHA1_Init( &shaContext );
984  SHA1_Update( &shaContext, inBuf, inBufSize );
985  SHA1_Final( outHash, &shaContext );
986  }
987  else {
988  if ( obfDebug ) {
989  printf( "obfMakeOneWayHash md5\n" );
990  }
991  MD5_Init( &md5Context );
992  MD5_Update( &md5Context, inBuf, inBufSize );
993  MD5_Final( outHash, &md5Context );
994  }
995  sprintf( outBuf, "%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x",
996  outHash[0], outHash[1], outHash[2], outHash[3],
997  outHash[4], outHash[5], outHash[6], outHash[7],
998  outHash[8], outHash[9], outHash[10], outHash[11],
999  outHash[12], outHash[13], outHash[14], outHash[15] );
1000 }
1001 
1002 
1003 /*
1004  Obfuscate a string using an input key
1005 */
1006 void
1007 obfEncodeByKey( const char *in, const char *key, char *out ) {
1008  /*
1009  Set up an array of characters that we will transpose.
1010  */
1011 
1012  int wheel_len = 26 + 26 + 10 + 15;
1013  int wheel[26 + 26 + 10 + 15];
1014 
1015  int i, j;
1016  int pc; /* previous character */
1017 
1018  unsigned char buffer[65]; /* each digest is 16 bytes, 4 of them */
1019  unsigned char keyBuf[101];
1020  char *cpOut;
1021  const char *cpIn;
1022  unsigned char *cpKey;
1023 
1024  if ( obfDebug ) {
1025  printf( "obfEncodeByKey enter key:%s:in:%s\n", key, in );
1026  }
1027 
1028  j = 0;
1029  for ( i = 0; i < 10; i++ ) {
1030  wheel[j++] = ( int )'0' + i;
1031  }
1032  for ( i = 0; i < 26; i++ ) {
1033  wheel[j++] = ( int )'A' + i;
1034  }
1035  for ( i = 0; i < 26; i++ ) {
1036  wheel[j++] = ( int )'a' + i;
1037  }
1038  for ( i = 0; i < 15; i++ ) {
1039  wheel[j++] = ( int )'!' + i;
1040  }
1041 
1042  memset( keyBuf, 0, sizeof( keyBuf ) );
1043  snprintf( ( char* )keyBuf, sizeof( keyBuf ), "%s", key );
1044  memset( buffer, 0, 17 );
1045 
1046  /*
1047  Get the MD5/SHA1 digest of the key to get some bytes with many
1048  different values.
1049  */
1050 
1052 
1053  /* Hash of the hash */
1055 
1056  /* Hash of 2 hashes */
1058 
1059  /* Hash of 2 hashes */
1061 
1062  cpIn = in;
1063  cpOut = out;
1064  if ( defaultHashType == HASH_TYPE_SHA1 ) {
1065  *cpOut++ = 's';
1066  *cpOut++ = 'h';
1067  *cpOut++ = 'a';
1068  *cpOut++ = '1';
1069  }
1070 
1071  cpKey = buffer;
1072  pc = 0;
1073  for ( ;; cpIn++ ) {
1074  int k, found;
1075  k = ( int ) * cpKey++;
1076  if ( cpKey > buffer + 60 ) {
1077  cpKey = buffer;
1078  }
1079  found = 0;
1080  for ( i = 0; i < wheel_len; i++ ) {
1081  if ( *cpIn == ( char )wheel[i] ) {
1082  j = i + k + pc;
1083  j = j % wheel_len;
1084  *cpOut++ = ( char )wheel[j];
1085  if ( cipherBlockChaining ) {
1086  pc = *( cpOut - 1 );
1087  pc = pc & 0xff;
1088  }
1089  found = 1;
1090  break;
1091  }
1092  }
1093  if ( found == 0 ) {
1094  if ( *cpIn == '\0' ) {
1095  *cpOut++ = '\0';
1096  if ( obfDebug ) printf( "obfEncodeByKey key:%s in:%s out:%s\n",
1097  key, in, out );
1098  return;
1099  }
1100  else {
1101  *cpOut++ = *cpIn;
1102  }
1103  }
1104  }
1105 }
1106 
1107 /*
1108  Obfuscate a string using an input key, version 2. Version two is
1109  like the original but uses two key and a hash of them instead of the
1110  key itself (to keep the key itself even more undiscoverable). The
1111  second key is a session signature (based on the challenge) (not
1112  secret but known to both client and server and unique for each
1113  connection). It also uses a quasi-cipher-block-chaining algorithm
1114  and adds a random character (so the 'out' is different even with the
1115  same 'in' each time).
1116 */
1117 #define V2_Prefix "A.ObfV2"
1119 void
1120 obfEncodeByKeyV2( const char *in, const char *key, const char *key2, char *out ) {
1121  struct timeval nowtime;
1122  char *myKey2;
1123  char myKey[200];
1124  char myIn[200];
1125  int rval;
1126 
1127  strncpy( myIn, V2_Prefix, 10 );
1128  strncat( myIn, in, 150 );
1129 
1130  strncpy( myKey, key, 90 );
1131  myKey[90] = '\0';
1132  strncat( myKey, key2, 100 );
1133 
1134  /*
1135  get a pseudo random number
1136  */
1137  ( void )gettimeofday( &nowtime, ( struct timezone * )0 );
1138  rval = nowtime.tv_usec & 0x1f;
1139  myIn[0] += rval; /* and add it to the leading character */
1140 
1141 
1142  myKey2 = obfGetMD5Hash( myKey );
1143 
1144  cipherBlockChaining = 1;
1145  obfEncodeByKey( myIn, myKey2, out );
1146  cipherBlockChaining = 0;
1147  return;
1148 }
1149 
1150 
1151 /*
1152  De-obfuscate a string using an input key
1153 */
1154 void
1155 obfDecodeByKey( const char *in, const char *key, char *out ) {
1156  /*
1157  Set up an array of characters that we will transpose.
1158  */
1159  int wheel_len = 26 + 26 + 10 + 15;
1160  int wheel[26 + 26 + 10 + 15];
1161 
1162  int i, j;
1163  int pc;
1164  unsigned char buffer[65]; /* each digest is 16 bytes, 4 of them */
1165  unsigned char keyBuf[101];
1166  char *cpOut;
1167  const char *cpIn;
1168  unsigned char *cpKey;
1169 
1170  int myHashType;
1171 
1172  if ( obfDebug ) {
1173  printf( "obfDecodeByKey enter key:%s: in:%s\n", key, in );
1174  }
1175 
1176  if ( strncmp( in, "sha1", 4 ) == 0 ) {
1177  in += 4;
1178  if ( obfDebug ) {
1179  printf( "using sha1 for decodebykey\n" );
1180  }
1181  myHashType = HASH_TYPE_SHA1;
1182  }
1183  else {
1184  if ( obfDebug ) {
1185  printf( "using md5 for decodebykey\n" );
1186  }
1187  myHashType = HASH_TYPE_MD5;
1188  }
1189 
1190  j = 0;
1191  for ( i = 0; i < 10; i++ ) {
1192  wheel[j++] = ( int )'0' + i;
1193  }
1194  for ( i = 0; i < 26; i++ ) {
1195  wheel[j++] = ( int )'A' + i;
1196  }
1197  for ( i = 0; i < 26; i++ ) {
1198  wheel[j++] = ( int )'a' + i;
1199  }
1200  for ( i = 0; i < 15; i++ ) {
1201  wheel[j++] = ( int )'!' + i;
1202  }
1203 
1204  memset( keyBuf, 0, sizeof( keyBuf ) );
1205  snprintf( ( char* )keyBuf, sizeof( keyBuf ), "%s", key );
1206 
1207  memset( buffer, 0, 65 );
1208 
1209  /*
1210  Get the MD5/SHA1 digest of the key to get some bytes with many
1211  different values.
1212  */
1213  obfMakeOneWayHash( myHashType, keyBuf, sizeof( keyBuf ) - 1, buffer );
1214 
1215  /* Hash of the hash */
1216  obfMakeOneWayHash( myHashType, buffer, 16, buffer + 16 );
1217 
1218  /* Hash of 2 hashes */
1219  obfMakeOneWayHash( myHashType, buffer, 32, buffer + 32 );
1220 
1221  /* Hash of 2 hashes */
1222  obfMakeOneWayHash( myHashType, buffer, 32, buffer + 48 );
1223 
1224  cpIn = in;
1225  cpOut = out;
1226  cpKey = buffer;
1227  pc = 0;
1228  for ( ;; cpIn++ ) {
1229  int k, found;
1230  k = ( int ) * cpKey++;
1231  if ( cpKey > buffer + 60 ) {
1232  cpKey = buffer;
1233  }
1234  found = 0;
1235  for ( i = 0; i < wheel_len; i++ ) {
1236  if ( *cpIn == ( char )wheel[i] ) {
1237  j = i - k - pc;
1238  while ( j < 0 ) {
1239  j += wheel_len;
1240  }
1241  *cpOut++ = ( char )wheel[j];
1242  if ( cipherBlockChaining ) {
1243  pc = *cpIn;
1244  pc = pc & 0xff;
1245  }
1246  found = 1;
1247  break;
1248  }
1249  }
1250  if ( found == 0 ) {
1251  if ( *cpIn == '\0' ) {
1252  *cpOut++ = '\0';
1253  if ( obfDebug ) printf( "obfDecodeByKey key:%s: in:%s out: %s\n",
1254  key, in, out );
1255  return;
1256  }
1257  else {
1258  *cpOut++ = *cpIn;
1259  }
1260  }
1261  }
1262 }
1263 
1264 /* Version 2, undoes V2 encoding.
1265  If encoding is not V2, handles is at V1 (original)
1266 */
1267 void
1268 obfDecodeByKeyV2( const char *in, const char *key, const char *key2, char *out ) {
1269  char *myKey2;
1270  static char myOut[200];
1271  int i, len, matches;
1272  char match[60];
1273  char myKey[200];
1274 
1275  strncpy( myKey, key, 90 );
1276  myKey[90] = '\0';
1277  strncat( myKey, key2, 100 );
1278 
1279  myKey2 = obfGetMD5Hash( myKey );
1280  cipherBlockChaining = 1;
1281  obfDecodeByKey( in, myKey2, myOut );
1282  cipherBlockChaining = 0;
1283 
1284  strncpy( match, V2_Prefix, 10 );
1285  len = strlen( V2_Prefix );
1286  matches = 1;
1287  for ( i = 1; i < len; i++ ) {
1288  if ( match[i] != myOut[i] ) {
1289  matches = 0;
1290  }
1291  }
1292  if ( matches == 0 ) {
1293  obfDecodeByKey( in, key, out );
1294  return;
1295  }
1296 
1297  strncpy( out, myOut + len, MAX_PASSWORD_LEN ); /* skip prefix */
1298  return;
1299 }
1300 
1301 /*
1302  Hash an input string
1303 */
1304 char *
1305 obfGetMD5Hash( const char *stringToHash ) {
1306  /*
1307  Set up an array of characters that we will transpose.
1308  */
1309  unsigned char buffer[30]; /* the digest is 16 bytes for MD5, 20 SHA1 */
1310  unsigned char keyBuf[101];
1311 
1312  static char outBuf[50];
1313 
1314  memset( keyBuf, 0, sizeof( keyBuf ) );
1315  snprintf( ( char* )keyBuf, sizeof( keyBuf ), "%s", stringToHash );
1316 
1317  memset( buffer, 0, sizeof( buffer ) );
1318  /*
1319  Get the MD5 (or SHA1) digest of the key
1320  */
1322 
1323  sprintf( outBuf, "%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x",
1324  buffer[0], buffer[1], buffer[2], buffer[3],
1325  buffer[4], buffer[5], buffer[6], buffer[7],
1326  buffer[8], buffer[9], buffer[10], buffer[11],
1327  buffer[12], buffer[13], buffer[14], buffer[15] );
1328  return outBuf;
1329 }
NULL
#define NULL
Definition: rodsDef.h:70
rodsPath.h
obfTempOps
int obfTempOps(int tmpOpt)
Definition: obf.cpp:379
obfDecodeByKey
void obfDecodeByKey(const char *in, const char *key, char *out)
Definition: obf.cpp:1155
obfiSetTimeFromFile
int obfiSetTimeFromFile(int fd)
Definition: obf.cpp:245
doTemp
int doTemp
Definition: obf.cpp:73
obfEncodeByKey
void obfEncodeByKey(const char *in, const char *key, char *out)
Definition: obf.cpp:1007
authenticate.h
obfiGetEnvKey
int obfiGetEnvKey()
Definition: obf.cpp:950
obfGetDefaultHashType
int obfGetDefaultHashType()
Definition: obf.cpp:964
HASH_TYPE_SHA1
#define HASH_TYPE_SHA1
Definition: obf.h:8
irods::experimental::administration::client::v1::exists
auto exists(rcComm_t &conn, const user &user) -> bool
Definition: user_administration.cpp:359
UNLINK_FAILED
@ UNLINK_FAILED
Definition: rodsErrorTable.h:502
obfEncodeByKeyV2
void obfEncodeByKeyV2(const char *in, const char *key, const char *key2, char *out)
Definition: obf.cpp:1120
obfSetDefaultHashType
void obfSetDefaultHashType(int type)
Definition: obf.cpp:956
TMP_FLAG
#define TMP_FLAG
Definition: obf.cpp:66
rcGlobalExtern.h
cipherBlockChaining
int cipherBlockChaining
Definition: obf.cpp:75
obftestmain
int obftestmain(int argc, char *argv[])
Definition: obf.cpp:85
AUTH_FILE_NOT_ENCRYPTED
@ AUTH_FILE_NOT_ENCRYPTED
Definition: rodsErrorTable.h:500
MAX_PASSWORD_LEN
#define MAX_PASSWORD_LEN
Definition: authenticate.h:9
ProcessType
int ProcessType
Definition: rcGlobal.cpp:16
obfiOpenOutFile
int obfiOpenOutFile(const char *fileName, int fileOpt)
Definition: obf.cpp:457
obfRmPw
int obfRmPw(int opt)
Definition: obf.cpp:212
obfDebug
int obfDebug
Definition: obf.cpp:70
keyBuf
void keyBuf(unsigned char *buf, int size, char *keyBuf)
Definition: utils.cpp:1003
obfiTimeval
int obfiTimeval()
Definition: obf.cpp:512
obfiWritePw
int obfiWritePw(int fd, const char *pw)
Definition: obf.cpp:502
obfGetMD5Hash
char * obfGetMD5Hash(const char *stringToHash)
Definition: obf.cpp:1305
FILE_WRITE_ERR
@ FILE_WRITE_ERR
Definition: rodsErrorTable.h:496
ENVIRONMENT_VAR_HOME_NOT_DEFINED
@ ENVIRONMENT_VAR_HOME_NOT_DEFINED
Definition: rodsErrorTable.h:498
irods.password_obfuscation.wheel
list wheel
Definition: password_obfuscation.py:28
MAX_NAME_LEN
#define MAX_NAME_LEN
Definition: rodsDef.h:61
obfSavePw
int obfSavePw(int promptOpt, int fileOpt, int printOpt, const char *pwArg)
Definition: obf.cpp:281
obfiTimeCheck
int obfiTimeCheck(int time1, int time2)
Definition: obf.cpp:707
obfSetDebug
int obfSetDebug(int opt)
Definition: obf.cpp:113
irods.pypyodbc.buffer
buffer
Definition: pypyodbc.py:46
obfMakeOneWayHash
void obfMakeOneWayHash(int hashType, unsigned const char *inBuf, int inBufSize, unsigned char *outHash)
Definition: obf.cpp:970
obfiEncode
void obfiEncode(const char *in, char *out, int extra)
Definition: obf.cpp:534
irods.pypyodbc.status
status
Definition: pypyodbc.py:467
CLIENT_PT
#define CLIENT_PT
Definition: rodsDef.h:77
termiosUtil.hpp
obfiDecode
int obfiDecode(const char *in, char *out, int extra)
Definition: obf.cpp:742
isTemp
int isTemp
Definition: obf.cpp:72
FILE_READ_ERR
@ FILE_READ_ERR
Definition: rodsErrorTable.h:495
int
typedef int((*funcPtr)())
obfDecodeByKeyV2
void obfDecodeByKeyV2(const char *in, const char *key, const char *key2, char *out)
Definition: obf.cpp:1268
obfGetPw
int obfGetPw(char *pw)
Definition: obf.cpp:159
match
int match(char *pattern, char *text)
irods::experimental::filesystem::client::remove
auto remove(rcComm_t &_comm, const path &_p, remove_options _opts=remove_options::none) -> bool
Definition: filesystem.cpp:699
obfiGetPw
int obfiGetPw(const char *fileName, char *pw)
Definition: obf.cpp:429
error
int error
Definition: filesystem.cpp:101
HASH_TYPE_DEFAULT
#define HASH_TYPE_DEFAULT
Definition: obf.h:9
NO_PASSWORD_ENTERED
@ NO_PASSWORD_ENTERED
Definition: rodsErrorTable.h:503
getRodsEnvAuthFileName
char * getRodsEnvAuthFileName()
Definition: getRodsEnv.cpp:63
AUTH_FILENAME_DEFAULT
#define AUTH_FILENAME_DEFAULT
Definition: obf.cpp:68
V2_Prefix
#define V2_Prefix
Definition: obf.cpp:1117
FILE_OPEN_ERR
@ FILE_OPEN_ERR
Definition: rodsErrorTable.h:494
obfiGetTv
int obfiGetTv(char *fileName)
Definition: obf.cpp:405
PASSWORD_EXCEEDS_MAX_SIZE
@ PASSWORD_EXCEEDS_MAX_SIZE
Definition: rodsErrorTable.h:497
UNABLE_TO_STAT_FILE
@ UNABLE_TO_STAT_FILE
Definition: rodsErrorTable.h:499
defaultHashType
static int defaultHashType
Definition: obf.cpp:79
buf
static char buf[64+50+1]
Definition: rsAuthRequest.cpp:21
manual_cleanup.out
out
Definition: manual_cleanup.py:29
type
int type
Definition: filesystem.cpp:103
HASH_TYPE_MD5
#define HASH_TYPE_MD5
Definition: obf.h:7
rods.h
timeVal
int timeVal
Definition: obf.cpp:71
AUTH_FILE_DOES_NOT_EXIST
@ AUTH_FILE_DOES_NOT_EXIST
Definition: rodsErrorTable.h:501
obfiGetFilename
int obfiGetFilename(char *fileName)
Definition: obf.cpp:119