![]() |
s i s t e m a o p e r a c i o n a l m a g n u x l i n u x | ~/ · documentação · suporte · sobre |
Next
Previous
Contents
8. Adding shadow support to a C programAdding shadow support to a program is actually fairly straightforward. The
only problem is that the program must be run by root (or SUID root) in order
for the the program to be able to access the This presents one big problem: very careful programming practices must be followed when creating SUID programs. For instance, if a program has a shell escape, this must not occur as root if the program is SUID root. For adding shadow support to a program so that it can check passwords, but
otherwise does need to run as root, it's a lot safer to run the program SUID
shadow instead. The In the example given below,
8.1 Header filesThe header files should reside in To add shadow support to a program, you need to include the header files: #include <shadow/shadow.h> #include <shadow/pwauth.h> It might be a good idea to use compiler directives to conditionally compile the shadow code (I do in the example below).
8.2 libshadow.a libraryWhen you installed the Shadow Suite the When compiling shadow support into a program, the linker needs to be told to
include the This is done by:
However, as we will see in the example below, most large programs use a
8.3 Shadow StructureThe struct spwd { char *sp_namp; /* login name */ char *sp_pwdp; /* encrypted password */ sptime sp_lstchg; /* date of last change */ sptime sp_min; /* minimum number of days between changes */ sptime sp_max; /* maximum number of days between changes */ sptime sp_warn; /* number of days of warning before password expires */ sptime sp_inact; /* number of days after password expires until the account becomes unusable. */ sptime sp_expire; /* days since 1/1/70 until account expires */ unsigned long sp_flag; /* reserved for future use */ }; The Shadow Suite can put things into the
This means that in addition to the password, the program
What this means is that we should use the function The author of the Shadow Suite indicates that since most programs in existence don't do this, and that it may be removed or changed in future versions of the Shadow Suite.
8.4 Shadow FunctionsThe extern void setspent __P ((void)); extern void endspent __P ((void)); extern struct spwd *sgetspent __P ((__const char *__string)); extern struct spwd *fgetspent __P ((FILE *__fp)); extern struct spwd *getspent __P ((void)); extern struct spwd *getspnam __P ((__const char *__name)); extern int putspent __P ((__const struct spwd *__sp, FILE *__fp)); The function that we are going to use in the example is:
8.5 ExampleThis is an example of adding shadow support to a program that needs it, but does not have it by default. This example uses the Point-to-Point Protocol Server (pppd-1.2.1d),
which has a mode in which it performs PAP authentication using
user names and passwords from the This feature of pppd probably isn't used very much, but if you installed the
Shadow Suite, it won't work anymore because the passwords are no
longer stored in The code for authenticating users under The following code needs to be added to the top of the file where all the
other
#ifdef HAS_SHADOW #include <shadow.h> #include <shadow/pwauth.h> #endif The next thing to do is to modify the actual code. We are still making
changes to the Function /* * login - Check the user name and password against the system * password database, and login the user if OK. * * returns: * UPAP_AUTHNAK: Login failed. * UPAP_AUTHACK: Login succeeded. * In either case, msg points to an appropriate message. */ static int login(user, passwd, msg, msglen) char *user; char *passwd; char **msg; int *msglen; { struct passwd *pw; char *epasswd; char *tty; if ((pw = getpwnam(user)) == NULL) { return (UPAP_AUTHNAK); } /* * XXX If no passwd, let them login without one. */ if (pw->pw_passwd == '\0') { return (UPAP_AUTHACK); } epasswd = crypt(passwd, pw->pw_passwd); if (strcmp(epasswd, pw->pw_passwd)) { return (UPAP_AUTHNAK); } syslog(LOG_INFO, "user %s logged in", user); /* * Write a wtmp entry for this user. */ tty = strrchr(devname, '/'); if (tty == NULL) tty = devname; else tty++; logwtmp(tty, user, ""); /* Add wtmp login entry */ logged_in = TRUE; return (UPAP_AUTHACK); } The user's password is placed into We will add the function Function
/* * login - Check the user name and password against the system * password database, and login the user if OK. * * This function has been modified to support the Linux Shadow Password * Suite if USE_SHADOW is defined. * * returns: * UPAP_AUTHNAK: Login failed. * UPAP_AUTHACK: Login succeeded. * In either case, msg points to an appropriate message. */ static int login(user, passwd, msg, msglen) char *user; char *passwd; char **msg; int *msglen; { struct passwd *pw; char *epasswd; char *tty; #ifdef USE_SHADOW struct spwd *spwd; struct spwd *getspnam(); #endif if ((pw = getpwnam(user)) == NULL) { return (UPAP_AUTHNAK); } #ifdef USE_SHADOW spwd = getspnam(user); if (spwd) pw->pw_passwd = spwd->sp-pwdp; #endif /* * XXX If no passwd, let NOT them login without one. */ if (pw->pw_passwd == '\0') { return (UPAP_AUTHNAK); } #ifdef HAS_SHADOW if ((pw->pw_passwd && pw->pw_passwd[0] == '@' && pw_auth (pw->pw_passwd+1, pw->pw_name, PW_LOGIN, NULL)) || !valid (passwd, pw)) { return (UPAP_AUTHNAK); } #else epasswd = crypt(passwd, pw->pw_passwd); if (strcmp(epasswd, pw->pw_passwd)) { return (UPAP_AUTHNAK); } #endif syslog(LOG_INFO, "user %s logged in", user); /* * Write a wtmp entry for this user. */ tty = strrchr(devname, '/'); if (tty == NULL) tty = devname; else tty++; logwtmp(tty, user, ""); /* Add wtmp login entry */ logged_in = TRUE; return (UPAP_AUTHACK); } Careful examination will reveal that we made another change as well. The
original version allowed access (returned So if we had set the original version up to run as the shell for a user i.e.
We fixed this also by returning Interestingly enough, Next we need to modify the Makefile so that two things occur:
Edit the Makefile, and add:
Then we find the line:
And change it to:
Now make and install.
Next Previous Contents |