summaryrefslogtreecommitdiff
path: root/pinyadmin/sbin/newuser
blob: ac3a51fb07b29fda43595d132ccf1f0600abda01 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#!/usr/bin/perl

use strict;
use warnings;

use Email::Valid::Loose qw( );

my ( $email, $username, $password );

# Configure the strictness of our email checks.
my $checker = Email::Valid::Loose->new
  ( "-fqdn"        => 1
  , "-fudge"       => 0
  , "-local_rules" => 0
  , "-mxcheck"     => 1
  , "-tldcheck"    => 0
  );

# Check to see if we're in batch mode.
if ( scalar @ARGV == 3 and $ARGV[0] eq "--batch" ) {

  ( undef, $email, $username ) = @ARGV;

  $email = $checker->address( $email );

  chomp( $password = <STDIN> );

# Some other incorrect argument arrangement.
} elsif ( scalar @ARGV ) {
  print "You can't pass any arguments to this script!\n";
  exit 2;
} else {

  # If they didn't provide a terminal definition, then assume xterm.
  # Everybody emulates xterm to at least a basic extent.
  if ( not exists $ENV{"TERM"} ) {
    $ENV{"TERM"} = "xterm";
    print "I don't know what terminal you're using; guessing xterm...\n";
  };

  # Disable buffering.
  $|++;

  my ( $password2 );

  while ( 1 ) {

    print "Email address to associate with new user: ";
    chomp ( $email = <STDIN> );

    if ( $email eq "" ) {
      print "You must provide an email address!\n";
      next;
    };

    $email = $checker->address( $email );
    if ( not defined $email ) {
      print "Please, at least pretend to provide a valid email address.\n";
      next;
    };

    last;

  };

  while ( 1 ) {

    print "Desired username: ";
    chomp ( $username = <STDIN> );

    if ( $username eq "" ) {
      print "You have to enter a username!\n";
      next;
    };

    if ( $username =~ /^(git|ikiwiki)-/ ) {
      print "Your username cannot start with git- or ikiwiki-!\n";
      next;
    };

    if ( $username !~ /^[a-zA-Z0-9_.][a-zA-Z0-9_.-]+$/ ) {
      print "Usernames must consist only of letters, digits, underscores, periods, and dashes, and not start with a dash. Usernames are case sensitive.\n";
      next
    };

    last;

  };

  while ( 1 ) {

    system( "stty", "-echo" );
    print "Desired password: ";
    chomp ( $password = <STDIN> );
    print "\nRetype password: ";
    chomp ( $password = <STDIN> );
    print "\n";
    system( "stty", "echo" );

    if ( $password ne $password2 ) {
      print "Provided passwords do not match; try again.\n";
      next;
    };

    if ( $password eq "" ) {
      print "You have to enter a password!\n";
      next;
    };

    last;

  };

};

# All the correctness checks should be repeated here. There are multiple
# pathways to get to this point, but only a single path from here on down. We
# don't need friendly error messages; whatever UI got us to this point *should*
# have already caught these.
exit 3 if ( not defined $email or $email eq "" );
exit 3 if ( not defined $username or $username eq "" );
exit 3 if ( $username =~ /^(git|ikiwiki)-/ );
exit 3 if ( $username !~ /^[a-zA-Z0-9_.][a-zA-Z0-9_.-]+$/ );
exit 3 if ( not defined $password or $password eq "" );

# Here on down is the actual creation code.

my @saltchars =
  ( 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
  , 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
  , '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
  , '.', '/'
  );

my $salt = "\$6\$";

foreach my $n ( 1 .. 16 ) {
  $salt .= $saltchars[int ( rand ( scalar @saltchars ) )];
};

$salt .= "\$";

my $crypt = crypt( $password, $salt );

my $ret = system( "/usr/sbin/useradd", "-c", "$email", "-k", "/var/empty", "-g", "users", "-m", "-p", $crypt, "-s", "/usr/bin/pinyshell", $username );

if ( $ret ) {
  print "An error occured creating the user; most likely, that username is already taken.\n";
  exit 1;
};

print "Your user has been created. Try logging in!\n";

exit 0;