2010-11-07 2 views
5

Ich muss überprüfen, eine Datei/etc/passwd ist gültig, und Gedanken Regex wäre eine gute Idee, um die Zeilen, die keine Kommentare sind zu überprüfen. Wie würde ich eine Zeile wie überprüfen:Regex Überprüfung der Zeile in/etc/passwd

root:*:0:0:System Administrator:/var/root:/bin/sh 

Nach einigen Recherchen, das 5. Feld (Systemadministrator) andere Daten wie E-Mail und Adresse enthalten kann, könnte das zweite Feld alles enthalten, sondern eine :, die letzten 2 Felder volle Wege.

Irgendwelche Hinweise, wie ich einen Regex-Ausdruck dafür erstellen würde?

+0

Die * passwd * -Handbuchseite lautet: "Die Kennwortdateien sollten niemals von Hand bearbeitet werden; * vipw * (8) sollte stattdessen verwendet werden. " – tchrist

Antwort

-2

So ähnlich?

^(#.*|[a-z]*:[^:]*:[0-9]*:[0-9]*:[^:]*:/[^:]*:/[^:]*)$ 

(unter der Annahme, dass der Benutzername aus Kleinbuchstaben besteht)

+1

Dieses Muster ist falsch. Es überprüft ungültige Passworteinträge. Das ist eine sehr schlechte Sache. – tchrist

+0

@tchrist: Ich weiß nicht genau, welche Formen Passworteinträge haben können, also ändere es bitte selbst. – thejh

5

ohne witzig zu sein - Passwd::Unix ist wahrscheinlich Ihre beste Wette.

+0

Sie bekommen sicherlich * meine * upvote. Eine Abstraktion auf höherer Ebene scheint kritisch zu sein. Egal, ich bin wirklich * wirklich * nervös, wenn ich die passwd-Datei berühre. [Seine Manpage] (http://www.openbsd.org/cgi-bin/man.cgi?query=passwd&apropos=0§ion=5&manpath=OpenBSD+Current&arch=i386&format=html) sagt, dass man nie etwas anderes verwenden soll, bis auf ' vipw', dessen Quelle [sehr vorsichtig] ist (http://www.openbsd.org/cgi-bin/man.cgi?query=pw_mkdb&apropos=0§ion=3&manpath=OpenBSD+Current&arch=i386&format=html). Dies ist zu wichtig, um ein Risiko einzugehen. – tchrist

1

Sie Sie Notwendigkeit Perl zu benutzen? Der normale Weg zur Überprüfung der Passwortdatei ist die Verwendung von awk als Datenbankabfragesprache. Zum Beispiel:

awk -F: '$3 ~ /pattern/' 

Natürlich könnten Sie perl -lane stattdessen verwenden. Aber wenn Sie Perl verwenden, sollten Sie wahrscheinlich das Standardmodul User::pwent verwenden.

+0

Würden nicht User :: Pwent am Ende alle Fehler verstecken, die es gibt? (Ich bin nicht sicher, genau * warum * das OP versucht,/etc/passwd zu verifizieren; scheint eine seltsame Sache zu sein) – ysth

+0

Oh, richtig, es würde. Sie sollten viel vorsichtiger sein als dies, wenn Sie */etc/passwd * Validierung !! Ich bin mir ziemlich sicher, dass * passwd * (5) auch keine '/^# /' Kommentare erlaubt, obwohl es mit YP immer schicker wird. – tchrist

1

Sie möchten einen regulären Ausdruck? Ok, dann werde ich geben Sie einen regulären Ausdruck: Es ist in der $is_valid_pwent_rx Variable.

Genießen.

WICHTIG: Diese darf nicht verkannt werden, eine Semantikprüfung einer gesunden passwd Datei zu sein. Es ist ein syntaktischer Checker nur.

Derzeit für OpenBSD konfiguriert.

#!/usr/bin/env perl 

use 5.010; 
use strict; 
use warnings; 

our $PASSWD = "/etc/passwd"; 

our $Errors = 0; 

sub is_valid_pwent(_); 
sub main(); 

######################################################### 

main(); 
exit($Errors != 0); 

######################################################### 

sub main() { 

    open(PASSWD)  || die "can't open $PASSWD: $!"; 

    while (my $line = <PASSWD>) { 
     chomp $line; 
     ## NEXT LINE IS WRONG: NO "COMMENTS" ALLOWED!!! 
     next if $line =~ /^#/; 
     next if is_valid_pwent($line); 
     say "$0: Invalid entry at $PASSWD $.: $line"; 
     $Errors++; 
    } 

    close(PASSWD)  || die "can't close $PASSWD: $!"; 

    say "$0: $PASSWD appears ok." unless $Errors; 
} 

######################################################### 

INIT { 

    state $is_valid_pwent_rx = qr{ 

    ^(?&any_pwent) $ 

############################################### 

     (?(DEFINE) 

     (?<any_pwent>  (?&yp_pwent) | (?&pwent)) 

# The `+' token may also be alone in the name field, which causes all users 
# from the passwd.byname and passwd.byuid YP maps to be included. 
# 
# If the entry contains non-empty uid or gid fields, the specified numbers 
# will override the information retrieved from the YP maps. Additionally, 
# if the gecos, dir, or shell entries contain text, it will override the 
# information included via YP. On some systems, the passwd field may also 
# be overridden. It is recommended that the standard way to enable YP 
# passwd support in /etc/master.passwd is: 
# 
#  +:*:::::::: 

     (?<yp_pwent> 
         (?&PLUS)   # substitute in YP 
     : (?&EMPTY) | (?&pw_passwd) # user's encrypted password. 
     : (?&EMPTY) | (?&pw_uid)  # user's login user ID. 
     : (?&EMPTY) | (?&pw_gid)  # user's login group ID. 
     : (?&EMPTY) | (?&pw_gecos)  # Honeywell login info. 
     : (?&EMPTY) | (?&pw_dir)  # user's home directory. 
     : (?&EMPTY) | (?&pw_shell)  # user's login shell. 
     ) 

# A normal password entry 

     (?<pwent> 

      (?&pw_name)  # user's login name. 
     : (?&pw_passwd) # user's encrypted password. 
     : (?&pw_uid)  # user's login user ID. 
     : (?&pw_gid)  # user's login group ID. 
     : (?&pw_gecos)  # Honeywell login info. 
     : (?&pw_dir)  # user's home directory. 
     : (?&pw_shell)  # user's login shell. 
     ) 

# A master password entry 

     (?<master_pwent> 
      (?&pw_name)  # user's login name. 
     : (?&pw_passwd) # user's encrypted password. 
     : (?&pw_uid)  # user's login user ID. 
     : (?&pw_gid)  # user's login group ID. 
     : (?&pw_class)  # user's general classification (see login.conf(5)) 
     : (?&pw_change) # password change time. 
     : (?&pw_expire) # account expiration time. 
     : (?&pw_gecos)  # general information about the user. 
     : (?&pw_dir)  # user's home directory. 
     : (?&pw_shell)  # user's login shell. 
     ) 

# The name field is the login used to access the computer account, and the 
# uid field is the number associated with it. They should both be unique 
# across the system (and often across a group of systems) since they con- 
# trol file access. 
# 
# While it is possible to have multiple entries with identical login names 
# and/or identical user IDs, it is usually a mistake to do so. Routines 
# that manipulate these files will often return only one of the multiple 
# entries, and that one by random selection. 
# 
# The login name may be up to 31 characters long. For compatibility with 
# legacy software, a login name should start with a letter and consist 
# solely of letters, numbers, dashes and underscores. The login name must 
# never begin with a hyphen (`-'); also, it is strongly suggested that nei- 
# ther uppercase characters nor dots (`.') be part of the name, as this 
# tends to confuse mailers. No field may contain a colon as this has been 
# used historically to separate the fields in the user database. 

     (?<pw_name> 

      (?= (?&NON_COLON){1,31}) 

      (?: (?&UNDERSCORE) 
       | (?&LETTER) 
      ) 

      (?: (?&LETTER) 
       | (?&number) 
       | (?&HYPHEN) 
       | (?&UNDERSCORE) 
      ){0,30} 

     ) 

# The password field is the *encrypted* form of the password. If the 
# password field is empty, no password will be required to gain access to 
# the machine. This is almost invariably a mistake. By convention, ac- 
# counts that are not intended to be logged in to (e.g. bin, daemon, sshd) 
# have a star (`*') in the password field. Note that there is nothing spe- 
# cial about `*', it is just one of many strings that is not a valid en- 
# crypted password (see crypt(3)). Because master.passwd contains the en- 
# crypted user passwords, it should not be readable by anyone without ap- 
# propriate privileges. 
# 
# Which type of cipher is used to encrypt the password information depends 
# on the configuration in login.conf(5). It can be different for local and 
# YP passwords. 

     (?<pw_passwd> 
      (?&STAR) 
      | (?&NON_COLON) + 
      | (?&EMPTY)   # should not allow this! 
     ) 

# The uid field is the numeric user ID assigned to this login name. 
# It need not strictly be unique. 

     (?<pw_uid> 
      (?&number) + 
     ) 

# The group (gid) field is the group that the user will be placed in 
# upon login. Since this system supports multiple groups (see groups(1)) 
# this field currently has little special meaning. 

     (?<pw_gid> 
      (?&number) + 
     ) 

     (?<pw_class> 
      (?&EMPTY) 
      | (?&any_text) 
     ) 

     (?<pw_change> 
      (?&EMPTY) 
      | (?&number) 
     ) 

     (?<pw_expire> 
      (?&EMPTY) 
      | (?&number) 
     ) 

     (?<pw_gecos> 
      # (?&EMPTY) | (?&gecos_fields) 
      (?&any_text) 
     ) 

     # some have an extra field in them after hphone 
     (?<gecos_fields> 
      (?&gecos_name) # User's full name. 
      (?&COMMA) 
      (?&gecos_office) # User's office location. 
      (?&COMMA) 
      (?&gecos_wphone) # User's work phone number. 
      (?&COMMA) 
      (?&gecos_hphone) # User's home phone number. 
     ) 

     (?<gecos_name>  (?&gecos_text) ) 
     (?<gecos_office> (?&gecos_text) ) 
     (?<gecos_wphone> (?&gecos_text) ) 
     (?<gecos_hphone> (?&gecos_text) ) 

     (?<pw_dir> 
      (?&EMPTY) # bad idea 
      | (?&directory_name) 
     ) 

     (?<pw_shell> 
      (?&EMPTY) # means "/bin/sh" 
      | (?&filename) 

     ) 

######################### 

     (?<directory_name>  (?&pathname) ) 
     (?<filename>   (?&pathname) ) 

     (?<pathname> 
      (?&SLASH) 
      (?&any_text) 
     ) 

     (?<LETTER>  [a-z]  ) # \p{Ll} && \p{ASCII} 

     (?<DIGIT>  [0-9]  ) # \p{Nd} && \p{ASCII} 
     (?<ZERO>   0   ) 
     (?<NON_ZERO> [1-9]  ) 

     (?<PLUS>  \x2B  ) # PLUS SIGN 
     (?<COMMA>  \x2C  ) # COMMA 
     (?<HYPHEN>  \x2D  ) # HYPHEN-MINUS 
     (?<SLASH>  \x2F  ) # SOLIDUS 
     (?<COLON>  \x3A  ) # COLON 
     (?<STAR>  \x2A  ) # ASTERISK 
     (?<UNDERSCORE> \x5F  ) # LOW LINE 

     (?<NON_COLON> [^\x3A]  ) 

     (?<EMPTY> (?# this space intentionally left blank)) 

     (?<number> 
      (?&ZERO) 
      | (?&NON_ZERO) (?&DIGIT) * 
     ) 

     (?<any_text> 
      (?&NON_COLON) * 
     ) 

     (?<gecos_text> 
      (?: 
       (?! (?&COMMA)) 
       (?! (?&COLON)) 
       . 
      ) * 
     ) 

    ) 

    }x; 

    sub is_valid_pwent(_) { 
     my $pwent = shift(); 
     return $pwent =~ $is_valid_pwent_rx; 
    } 

} 
Verwandte Themen