PageRenderTime 54ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/sfsauthd/upgradedb.pl

https://github.com/dougc333/sfs_eventdrivenc--templatelibrary
Perl | 257 lines | 219 code | 31 blank | 7 comment | 24 complexity | 29827fffe5d6de40abc121b692e5ed31 MD5 | raw file
  1. #!/usr/bin/perl
  2. # $Id: upgradedb.pl,v 1.3 2002/10/19 13:03:10 max Exp $
  3. #
  4. # upgradedb.pl
  5. #
  6. # Upgrades SfS text Auth DBs (i.e. sfs_users) from v1 to v2.
  7. #
  8. use IO::File;
  9. use IO::Pipe;
  10. use POSIX qw(strftime);
  11. use strict;
  12. use vars qw [ $LOCATE $SFS_USERS @SFS_CONF_DIRS %FIELDS ];
  13. $LOCATE = "locate";
  14. $SFS_USERS = "sfs_users";
  15. @SFS_CONF_DIRS = qw [ /etc/sfs ];
  16. %FIELDS = ( user => 0, pubkey => 1, privs => 2, srpinfo => 3, privkey => 4);
  17. sub usage () {
  18. print <<EOF;
  19. usage: ugradedb.pl [-a | -s] [-n] <file1> <file2> ....
  20. -a Use "locate" command to find all sfs_users and sfs_users.pub
  21. files on the system. Will then interactively prompt for each
  22. file.
  23. -n Turn off interactive prompting.
  24. -s (default) Look for sfs_users and sfs_users.pub files in standard
  25. sfs directories.
  26. If neither the -a or the -s flag is provided, and specific
  27. filenames are provided, then those files will be converted
  28. without the interactive prompting.
  29. EOF
  30. exit (0);
  31. }
  32. sub find_locate () {
  33. my @path = split /:/, $ENV{PATH};
  34. foreach (@path) {
  35. my $prog = $_ . "/" . $LOCATE;
  36. return $prog if -x $prog;
  37. }
  38. return "";
  39. };
  40. sub find () {
  41. my $prog = find_locate ();
  42. unless ($prog) {
  43. warn "Could not find locate command in your path.\n";
  44. return ();
  45. }
  46. my $pipe = new IO::Pipe ();
  47. $pipe->reader ("$prog $SFS_USERS");
  48. my @ret;
  49. while (<$pipe>) {
  50. chomp;
  51. next unless m#(^|/)?$SFS_USERS(.pub)?$#;
  52. push @ret, $_;
  53. }
  54. return @ret;
  55. }
  56. sub find_sfs () {
  57. my @ret;
  58. foreach my $path (@SFS_CONF_DIRS) {
  59. foreach my $suffix ("", ".pub") {
  60. my $file = $path . "/" . $SFS_USERS . $suffix;
  61. push @ret, $file if -r $file;
  62. }
  63. }
  64. return @ret;
  65. }
  66. sub parse_argv (\$) {
  67. my ($promptr) = @_;
  68. my @files;
  69. $$promptr = 0;
  70. my $noprompt = 0;
  71. if ($#ARGV >= 0) {
  72. if ($ARGV[0] =~ /^-(.*)/) {
  73. my $opt = $1;
  74. if ($opt eq "a") {
  75. @files = find ();
  76. $$promptr = 1;
  77. } elsif ($opt eq "s") {
  78. @files = find_sfs ();
  79. $$promptr = 1;
  80. } elsif ($opt eq "n") {
  81. $noprompt = 1;
  82. } else {
  83. usage ();
  84. }
  85. usage () if $#ARGV > 0;
  86. } else {
  87. @files = @ARGV ;
  88. }
  89. }
  90. if ($#files < 0) {
  91. @files = find_sfs ();
  92. $$promptr = 1;
  93. }
  94. $$promptr = 0 if $noprompt;
  95. return @files;
  96. }
  97. sub do_file ($$) {
  98. my ($file, $prompt) = @_;
  99. my $err;
  100. unless (-r $file) {
  101. warn "** $file: cannot open for reading\n";
  102. return 0;
  103. }
  104. if (is_v2 ($file)) {
  105. warn "** $file: already contains converted entries\n";
  106. return 0;
  107. }
  108. my @lns;
  109. unless (@lns = parse_file ($file)) {
  110. return 0;
  111. }
  112. if ($prompt and !get_yes ($file)) {
  113. return 0;
  114. }
  115. return convert_file ($file, \@lns);
  116. }
  117. sub backup_file ($\$) {
  118. my ($fn, $nfn) = @_;
  119. my $n = 0;
  120. do {
  121. $$nfn = $fn . ".v1-saved-" . ++$n;
  122. } while ( -e $$nfn );
  123. rename ($fn, $$nfn);
  124. unless (-r $$nfn) {
  125. warn "** $fn: File rename ($fn to $$nfn) failed\n";
  126. return 0;
  127. }
  128. return 1;
  129. }
  130. sub sfsts () {
  131. return strftime "%a, %b %d %Y %H.%M.%S %z", gmtime;
  132. }
  133. sub convert_file ($$) {
  134. my ($fn, $lines) = @_;
  135. my $nfn;
  136. my @fstats = stat ($fn);
  137. return 0 unless backup_file ($fn, $nfn);
  138. umask (0077);
  139. my $fh = new IO::File ($fn, "w", $fstats[2] );
  140. foreach my $line (@$lines) {
  141. my $user = $line->[$FIELDS{user}];
  142. my @pwent = getpwnam ($user);
  143. my $audit = "Converted from v1 on " . sfsts ();
  144. my @out = ( "USER", # 0
  145. $user, # 1
  146. $pwent[2], # 2
  147. 1, # 3 -- version
  148. $pwent[3], # 4
  149. "", # 5 -- owner
  150. "rabin," . $line->[$FIELDS{pubkey}], # 6
  151. $line->[$FIELDS{privs}], # 7
  152. $line->[$FIELDS{srpinfo}], # 8
  153. $line->[$FIELDS{privkey}], # 9
  154. "", # 10 -- srvprivkey
  155. $audit ); # 11
  156. print $fh join (":", @out), "\n";
  157. }
  158. $fh->close ();
  159. if ($fstats[2] & 0x77 and !($fn =~ /\.pub$/ )) {
  160. warn "** $fn: WARNING! File is readable by group/all\n";
  161. }
  162. chown $fstats[4], $fstats[5], $fn;
  163. chmod $fstats[2], $fn;
  164. print "$fn: converted (backup file at $nfn)\n";
  165. return 1;
  166. }
  167. sub is_v2 ($) {
  168. my ($fn) = @_;
  169. my $fh = new IO::File ("<$fn");
  170. return 0 unless $fh;
  171. my $ret = 0;
  172. while (<$fh>) {
  173. if ( m#^(USER|GROUP):[A-Za-z_/-]{0,31}:\d+:# ) {
  174. $ret = 1;
  175. last;
  176. }
  177. }
  178. $fh->close ();
  179. return $ret;
  180. }
  181. sub parse_file ($) {
  182. my ($fn, $arr) = @_;
  183. my $fh = new IO::File ("<$fn");
  184. unless ($fh) {
  185. warn "** $fn: cannot open for reading\n";
  186. return ();
  187. }
  188. my @lns;
  189. my $line;
  190. my $lineno = 1;
  191. while ($line = <$fh>) {
  192. chomp ($line);
  193. $line =~ s/#.*//;
  194. next unless $line =~ /\S/ ;
  195. my @fields = split /:/, $line;
  196. if ($#fields < 2 || $#fields > 4) {
  197. warn "** $fn:$lineno: Parse error: wrong number of fields\n";
  198. return ();
  199. }
  200. unless ( $fields[$FIELDS{user}] =~ m!^[\w_/-]+$! ) {
  201. warn "** $fn:$lineno: Parse error: invalid user name";
  202. return ();
  203. }
  204. unless ( $fields[$FIELDS{pubkey}] =~ m!^0x[a-f0-9]+$! ) {
  205. warn "** $fn:$lineno: Parse error: invalid public key\n";
  206. return ();
  207. }
  208. push @lns, [ @fields ];
  209. $lineno++;
  210. }
  211. return @lns;
  212. }
  213. sub get_yes ($) {
  214. my ($file) = @_;
  215. my $ans;
  216. do {
  217. print "Convert file $file? (yes/no) ";
  218. chomp ($ans = lc (<STDIN>));
  219. } while (!($ans eq "yes" or $ans eq "no"));
  220. return ($ans eq "yes");
  221. }
  222. my $prompt;
  223. my @files = parse_argv ($prompt);
  224. foreach (@files) {
  225. do_file ($_, $prompt);
  226. }