Services Backend

scripts.mit.edu

Quentin Smith Anders Kaseorg

scripts@mit.edu

Student Information Processing Board

October 8, 2007

Quentin Smith, Anders Kaseorg scripts@mit.edu  scripts.mit.edu

Services Backend

Outline

1 Services

Web Mail Cron (“Shortjobs”) SQL AFS

2 Backend

Kerberos

Services Backend

Outline

1 Services

Web Mail Cron (“Shortjobs”) SQL AFS

2 Backend

Kerberos

Services Backend Web Mail Cron (“Shortjobs”) SQL

Apache

Everyone wants Apache Apache’s default configuration isn’t safe for scripting Scripting requires code execution - mod php, mod perl, mod python Apache normally runs everything as apache/nobody How to secure? suxec - allows Apache to spawn a process as the user… … even for static content!

Services Backend Web Mail Cron (“Shortjobs”) SQL

Apache

Everyone wants Apache Apache’s default configuration isn’t safe for scripting Scripting requires code execution - mod php, mod perl, mod python Apache normally runs everything as apache/nobody How to secure? suxec - allows Apache to spawn a process as the user… … even for static content!

Services Backend Web Mail Cron (“Shortjobs”) SQL

suexec

setuid program Passed the request by Apache Verifies that the script is in the web scripts directory Switches to the uid of the file and executes Even for static files!

Services Backend Web Mail Cron (“Shortjobs”) SQL

Postfix

Standard Postfix server No local mailboxes All mail is passed to procmail

mailbox_command = /usr/bin/procmail -t \
-a "\${EXTENSION}" ~/mail_scripts/procmailrc

Services Backend Web Mail Cron (“Shortjobs”) SQL

procmail

Reads ~/mail_scripts/procmailrc from user’s home

directory Users can do whatever they want with messages AFS causes problems - No way to know if failure is temporary (file server is down) or permanent (user isn’t signed up for mail scripts) All procmail failures are treated as temporary, so mail is queued

Services Backend Web Mail Cron (“Shortjobs”) SQL

Vixie Cron

Crontabs are currently stored locally on scripts servers cronload command loads the crontabs from

~/cron_scripts/crontab

Needs improvement Cron does not fail over with Web and Mail Plan to move crontabs into AFS and do hot failover

Services Backend Web Mail Cron (“Shortjobs”) SQL

Vixie Cron

Crontabs are currently stored locally on scripts servers cronload command loads the crontabs from

~/cron_scripts/crontab

Needs improvement Cron does not fail over with Web and Mail Plan to move crontabs into AFS and do hot failover

Services Backend Web Mail Cron (“Shortjobs”) SQL

sql.mit.edu

Though scripts.mit.edu makes use of sql.mit.edu, it’s a separate SIPB service with different maintainers.

sql.mit.edu provides MySQL databases to scripts users and anyone else SQL data is stored locally, replicated across multiple servers Nightly backups go into AFS

Services Backend  AFS Kerberos

AFS access controls

AFS enforces server side access controls. On Athena systems: user’s password → Kerberos tickets → AFS tokens, which authenticate the client to the AFS server. On scripts, we don’t have the user’s password or tickets. User’s scripts are not publicly readable. Access is controlled through a single daemon.scripts AFS user.

Services Backend  AFS Kerberos

Isolating users on scripts

If all users share daemon.scripts AFS tokens, how are they prevented from accessing each other’s web scripts? On scripts, we enforce additional restrictions in the AFS kernel module.

    afsAccessOK() in
    openafs/src/afs/VNOPS/afs vnop access.c

Services Backend  AFS Kerberos

You can only use daemon.scripts credentials to access files in a volume with volume ID equal to your UID,

 int
 afs_AccessOK(struct vcache *avc, afs_int32 arights,
              struct vrequest *areq, afs_int32 check_mode_bits)
 {
     ...
+    if (!(areq->realuid == avc->fid.Fid.Volume) &&
+        !((avc->anyAccess | arights) == avc->anyAccess) &&
+        !(arights == PRSFS_LOOKUP && areq->realuid == HTTPD_UID) &&
+        !(arights == PRSFS_LOOKUP && areq->realuid == POSTFIX_UID) &&
+        !(arights == PRSFS_READ && areq->realuid == HTTPD_UID &&
+          avc->m.Mode == 0100777) &&
+        !(PRSFS_USR3 == afs_GetAccessBits(avc, PRSFS_USR3, areq) &&
+          areq->realuid == 0) &&
+        !(PRSFS_USR4 == afs_GetAccessBits(avc, PRSFS_USR4, areq) &&
+          (areq->realuid == 0 || areq->realuid == SIGNUP_UID))) {
+       return 0;
+    }
     ...

Quentin Smith, Anders Kaseorg scripts@mit.edu  scripts.mit.edu

Services Backend  AFS Kerberos

or the file is system:anyuser readable anyway,

 int
 afs_AccessOK(struct vcache *avc, afs_int32 arights,
              struct vrequest *areq, afs_int32 check_mode_bits)
 {
     ...
+    if (!(areq->realuid == avc->fid.Fid.Volume) &&
+        !((avc->anyAccess | arights) == avc->anyAccess) &&
+        !(arights == PRSFS_LOOKUP && areq->realuid == HTTPD_UID) &&
+        !(arights == PRSFS_LOOKUP && areq->realuid == POSTFIX_UID) &&
+        !(arights == PRSFS_READ && areq->realuid == HTTPD_UID &&
+          avc->m.Mode == 0100777) &&
+        !(PRSFS_USR3 == afs_GetAccessBits(avc, PRSFS_USR3, areq) &&
+          areq->realuid == 0) &&
+        !(PRSFS_USR4 == afs_GetAccessBits(avc, PRSFS_USR4, areq) &&
+          (areq->realuid == 0 || areq->realuid == SIGNUP_UID))) {
+       return 0;
+    }
     ...

Quentin Smith, Anders Kaseorg scripts@mit.edu  scripts.mit.edu

Services Backend  AFS Kerberos

or the apache or postfix users are doing a stat(),

 int
 afs_AccessOK(struct vcache *avc, afs_int32 arights,
              struct vrequest *areq, afs_int32 check_mode_bits)
 {
     ...
+    if (!(areq->realuid == avc->fid.Fid.Volume) &&
+        !((avc->anyAccess | arights) == avc->anyAccess) &&
+        !(arights == PRSFS_LOOKUP && areq->realuid == HTTPD_UID) &&
+        !(arights == PRSFS_LOOKUP && areq->realuid == POSTFIX_UID) &&
+        !(arights == PRSFS_READ && areq->realuid == HTTPD_UID &&
+          avc->m.Mode == 0100777) &&
+        !(PRSFS_USR3 == afs_GetAccessBits(avc, PRSFS_USR3, areq) &&
+          areq->realuid == 0) &&
+        !(PRSFS_USR4 == afs_GetAccessBits(avc, PRSFS_USR4, areq) &&
+          (areq->realuid == 0 || areq->realuid == SIGNUP_UID))) {
+       return 0;
+    }
     ...

Quentin Smith, Anders Kaseorg scripts@mit.edu  scripts.mit.edu

Services Backend  AFS Kerberos

or the apache user is trying to read a file with mode 777,

 int
 afs_AccessOK(struct vcache *avc, afs_int32 arights,
              struct vrequest *areq, afs_int32 check_mode_bits)
 {
     ...
+    if (!(areq->realuid == avc->fid.Fid.Volume) &&
+        !((avc->anyAccess | arights) == avc->anyAccess) &&
+        !(arights == PRSFS_LOOKUP && areq->realuid == HTTPD_UID) &&
+        !(arights == PRSFS_LOOKUP && areq->realuid == POSTFIX_UID) &&
+        !(arights == PRSFS_READ && areq->realuid == HTTPD_UID &&
+          avc->m.Mode == 0100777) &&
+        !(PRSFS_USR3 == afs_GetAccessBits(avc, PRSFS_USR3, areq) &&
+          areq->realuid == 0) &&
+        !(PRSFS_USR4 == afs_GetAccessBits(avc, PRSFS_USR4, areq) &&
+          (areq->realuid == 0 || areq->realuid == SIGNUP_UID))) {
+       return 0;
+    }
     ...

Quentin Smith, Anders Kaseorg scripts@mit.edu  scripts.mit.edu

Services Backend  AFS Kerberos

or the root or signup users are accessing file with the special D or E bits.

 int
 afs_AccessOK(struct vcache *avc, afs_int32 arights,
              struct vrequest *areq, afs_int32 check_mode_bits)
 {
     ...
+    if (!(areq->realuid == avc->fid.Fid.Volume) &&
+        !((avc->anyAccess | arights) == avc->anyAccess) &&
+        !(arights == PRSFS_LOOKUP && areq->realuid == HTTPD_UID) &&
+        !(arights == PRSFS_LOOKUP && areq->realuid == POSTFIX_UID) &&
+        !(arights == PRSFS_READ && areq->realuid == HTTPD_UID &&
+          avc->m.Mode == 0100777) &&
+        !(PRSFS_USR3 == afs_GetAccessBits(avc, PRSFS_USR3, areq) &&
+          areq->realuid == 0) &&
+        !(PRSFS_USR4 == afs_GetAccessBits(avc, PRSFS_USR4, areq) &&
+          (areq->realuid == 0 || areq->realuid == SIGNUP_UID))) {
+       return 0;
+    }
     ...

Quentin Smith, Anders Kaseorg scripts@mit.edu  scripts.mit.edu

Group locker support

“Users” on scripts are actually lockers. User IDs are actually locker volume IDs. Kerberos is modified to let users SSH in as any locker they administrate.

Replaced the .k5login mechanism: krb5 kuserok() in

krb5/src/lib/krb5/os/kuserok.c

Calls a Perl script /usr/local/sbin/admof to do the actual check.

Group locker support

“Users” on scripts are actually lockers. User IDs are actually locker volume IDs. Kerberos is modified to let users SSH in as any locker they administrate.

Replaced the .k5login mechanism: krb5 kuserok() in

krb5/src/lib/krb5/os/kuserok.c

Calls a Perl script /usr/local/sbin/admof to do the actual check.

 krb5_boolean KRB5_CALLCONV
 krb5_kuserok(krb5_context context, krb5_principal principal,
              const char *luser)
 {
     ...
+    if ((pid = fork()) == -1) {
+       free(princname);
+       return(FALSE);
+    }
+    if (pid == 0) {
+#define ADMOF_PATH "/usr/local/sbin/ssh-admof"
+        exec(ADMOF_PATH, ADMOF_PATH, (char *) luser, princname, NULL);
+        exit(1);
+    }
+    if (waitpid(pid, &status, 0) > 0 && WIFEXITED(status) &&
+        WEXITSTATUS(status) == 33) {
+        isok = TRUE;
+    }
     ...
 }

Quentin Smith, Anders Kaseorg scripts@mit.edu  scripts.mit.edu