ÀÌÀüÆäÀÌÁö ´ÙÀ½ÆäÀÌÁö Â÷·Ê

8. C program¿¡ Shadow¸¦ Áö¿øÇϵµ·Ï µ¡ºÙÀ̱â

C program¿¡ Shadow¸¦ Áö¿øÇϵµ·Ï µ¡ºÙÀÌ´Â °ÍÀº ½ÇÁ¦ÀûÀ¸·Î ¸Å¿ì °£´ÜÇÏ´Ù. ´ÜÁö ¹®Á¦´Â /etc/shadow file¿¡ Á¢±ÙÇϱâ À§Çؼ­´Â programÀÌ root(¶Ç´Â SUID root)·Î ½ÇÇàµÇ¾î¾ß ÇÑ´Ù´Â °ÍÀÌ´Ù.

ÀÌ °ÍÀº Ä¿´Ù¶õ ¹®Á¦ Çϳª¸¦ ¿ì¸®¿¡°Ô °­¿äÇÑ´Ù: SUID programÀ» ¸¸µé ¶§, ¸Å¿ì Á¶½É½º·´°Ô programmingÇÏ´Â ½À°üÀÌ µÇ¾î ÀÖ¾î¾ß ÇÑ´Ù. ¿¹¸¦ µé¾î, programÀÌ shell Å»Ãâ±â´ÉÀ» °¡Áö°í ÀÖ°í ÀÌ programÀÌ SUID root¶ó¸é, ÀÌ ±â´ÉÀÌ root ±ÇÇÑÀ» Á־´Â ¾ÈµÈ´Ù.

password¸¦ °Ë»çÇØ ÇÒ ¼ö ÀÖÁö¸¸ ´Ù¸¥ °æ¿ì´Â root±ÇÇÑÀ¸·Î ½ÇÇàÇÒ ÇÊ¿ä°¡ ¾ø´Â program¿¡ shadow Áö¿ø ±â´ÉÀ» µ¡ºÙÀÓÀ¸·Î½á, SUID programº¸´Ù ÈξÀ ¾ÈÀüÇÑ programÀ» ¸¸µé ¼ö ÀÖ°Ô ÇÑ´Ù. xlock programÀÌ ±× ÇÑ ¿¹ÀÌ´Ù.

¾Æ·¡ ¿¹¿¡¼­, pppd-1.2.1d´Â ÀÌ¹Ì SUID root·Î ½ÇÇàÇÏ°í ÀÖÀ¸¹Ç·Î, shadow Áö¿ø ±â´ÉÀ» µ¡ºÙÀÌ´Â °ÍÀº programÀÌ ´õ Ãë¾àÇÏ°Ô ¸¸µéÁö ¾ÊÀ» °ÍÀÌ´Ù.

8.1 Header files

header fileµéÀº /usr/include/shadow¿¡ ÀÖ´Ù. ¶ÇÇÑ, /usr/include/shadow.hµµ ÀÖ´Ù. ±×·¯³ª, ÀÌ°ÍÀº /usr/include/shadow/shadow.h¿¡ ´ëÇÑ symbolic linkÀÏ °ÍÀÌ´Ù.

shadow Áö¿ø ±â´ÉÀ» Ãß°¡Çϱâ À§ÇØ, header fileÀ» ³ÖÀÚ:

#include <shadow/shadow.h>
#include <shadow/pwauth.h>

shadow code¸¦ »óȲ¿¡ µû¶ó compileÇϵµ·Ï compiler directive(Áö½ÃÀÚ)¸¦ ¾²´Â °ÍÀº Á¾Àº ¹æ¹ýÀÌ´Ù (¾Æ·¡ ¿¹¿¡¼­ º¸µµ·Ï).

8.2 libshadow.a library

Shadow SuiteÀ» ¼³Ä¡ÇÒ ¶§, libshadow.a fileÀº /usr/lib¿¡ ³õÀδÙ.

shadow Áö¿ø±â´ÉÀ» program¿¡ ³ÖÀ»·Á¸é, linker¿¡°Ô libshadow.a¸¦ °°ÀÌ linkÇϵµ·Ï Áö½ÃÇØÁÖ¾î¾ß ÇÑ´Ù.

´ÙÀ½Ã³·³:

gcc program.c -o program -lshadow

¾î·µç, ¾Æ·¡ ¿¹¿¡¼­ º¸´Ù½ÃÇÇ, ´ëºÎºÐ °Å´ëÇÑ programµéÀº MakefileÀ» »ç¿ëÇÏ°í, ¿ì¸®°¡ °íÄ¥ LIBS=...¶ó´Â º¯¼ö¸¦ ´ë°³ ¾´´Ù.

8.3 Shadow ±¸Á¶Ã¼

libshadow.a library´Â /etc/shadow file·ÎºÎÅÍ ¾ò´Â Á¤º¸¸¦ spwd¶ó´Â ±¸Á¶Ã¼¿¡ ´ã´Â´Ù. spwd ±¸Á¶Ã¼¿¡ ´ëÇÑ Á¤ÀÇ´Â /usr/include/shadow/shadow.h file¿¡ ÀÖ´Ù:


struct spwd
{
  char *sp_namp;                /* »ç¿ëÀÚ À̸§ */
  char *sp_pwdp;                /* encryptµÈ password */
  sptime sp_lstchg;             /* ÃÖ±Ù data ¼öÁ¤ÀÏ */
  sptime sp_min;                /* ¼öÁ¤ÀÛ¾÷°£ÀÇ ÃÖ¼Ò ³¯Â¥(°á±¹ Çѹø ¼öÁ¤ÇÑ
                                   ´ÙÀ½ ¾ðÁ¦ ¼öÁ¤ÀÌ °¡´ÉÇÑ°¡¿¡ ´ëÇÑ ´ë´ä) */
  sptime sp_max;                /* ¼öÁ¤ÀÛ¾÷°£ÀÇ ÃÖ´ë ³¯Â¥(password À¯È¿±â°£) */
  sptime sp_warn;               /* password°¡ ¹«È¿°¡ µÇ±â Àü °æ°íÇÏ´Â ±â°£ */
  sptime sp_inact;              /* password°¡ ¹«È¿µÈ µÚ, °èÁ¤ÀÌ »ç¿ëºÒ´ÉÀÌ
                                   µÉ ¶§±îÁöÀÇ ±â°£. */
  sptime sp_expire;             /* ³¯Â¥(°èÁ¤»ç¿ëºÒ´É - 1/1/70) */
  unsigned long sp_flag;        /* ³ªÁßÀ» À§ÇØ ºñ¿öµÒ */
};

Shadow Suite´Â sp_pwdp field¿¡ encodeµÈ passwd¿Í ÇÔ²² ´Ù¸¥ °É ³ÖÀ» ¼ö ÀÖ´Ù. password field´Â ´ÙÀ½Ã³·³ µÉ ¼ö ÀÖ´Ù:

username:Npge08pfz4wuk;@/sbin/extra:9479:0:10000::::

ÀÌ´Â password¿¡ µ¡ºÙ¿©, /sbin/extra programÀÌ ´õ ½ÉÈ­µÈ ÀÎÁõÀ» À§ÇØ È£ÃâµÈ´Ù´Â °ÍÀ» ÀǹÌÇÑ´Ù. È£ÃâµÇ´Â programÀº username, È£ÃâÀÌÀ¯¸¦ ¾Ë·ÁÁÖ´Â switch¸¦ ¹ÞÀ» ¼ö ÀÖ¾î¾ß µÉ °ÍÀÌ´Ù. ÀÚ¼¼ÇÑ °É ¾Ë°í ½Í´Ù¸é, /usr/include/shadow/pwauth.h¿Í pwauth.c¸¦ º¸±â ¹Ù¶õ´Ù.

ÀÌ°ÍÀÌ ÀǵµÇÏ´Â ¹Ù´Â -µÎ¹ø »ç¿ëÀÚ È®ÀÎÇÏ´Â µ¥ »ç¿ëÇÒ ¼öµµ ÀÖ´Â- ´Ù¸¥ ÇöÁ¸ÇÏ´Â(actual) »ç¿ëÀÚ È®ÀÎ ¹æ¹ýÀ» ¼öÇàÇÒ ¼ö ÀÖµµ·Ï pwauth ±â´ÉÀ» ¾²´Â °ÍÀÌ´Ù.

Shadow SuiteÀÇ ÀúÀÚ´Â ÇöÁ¸ÇÏ´Â ´ëºÎºÐÀÇ programµéÀÌ ÀÌ ±â´ÉÀ» ¾²°í ÀÖÁö ¾ÊÀ½Àº ÁöÀûÇϸ鼭, Shadow Suite Â÷±â version¿¡´Â »ç¶óÁö°Å³ª, ¹Ù²ð °ÍÀ̶ó°í ÇÑ´Ù.

8.4 Shadow ÇÔ¼öµé

shadow.h fileÀº libshadow.a library¿¡ ÀÖ´Â ÇÔ¼öµéÀÇ ±âº»ÇüÀ» Æ÷ÇÔÇÏ°í ÀÖ´Ù:


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));

¿¹Á¦¿¡¼­ ¾µ ÇÔ¼ö´Â: getspnam - spwd ±¸Á¶Ã¼¿¡¼­ »ç¿ëÀÚ À̸§À» °¡Á®¿À´Â ÇÔ¼ö - ÀÌ´Ù.

8.5 Example

ÀÌ°ÍÀº shadow Áö¿ø±â´ÉÀÌ ÇÊ¿äÇÏÁö¸¸ ±âº»¼³Á¤À¸·Î µÇ¾î ÀÖÁö ¾ÊÀº program¿¡ ±×°ÍÀ» Ãß°¡ÇÏ´Â ¿¹Á¦ÀÌ´Ù.

º» ¿¹Á¦·Î, PAPÀ̳ª CHAP´ë½Å /etc/passwd file¿¡ ÀÖ´Â »ç¿ëÀÚÀ̸§°ú password¸¦ »ç¿ëÇÏ¿© PAP ÀÎÁõÀ» ¼öÇàÇÏ´Â mode¸¦ Áö´Ñ, Point-to-Point Protocol Server (pppd-1.2.1d)¸¦ µé°í ÀÖ´Ù.

pppdÀÇ ÀÌ·± ±â´ÉÀº ±×¸® ÀÚÁÖ ¾²ÀÌ°í ÀÖÁö ¾Ê´Ù. ±×·¯³ª Shadow Suite°¡ ¼³Ä¡µÇ¸é ÀÌ ±â´ÉÀº ¸ø ¾²°Ô µÉ °ÍÀÌ´Ù. ¿Ö³ÄÇϸé password´Â ´õ ÀÌ»ó /etc/passwd¿¡ ÀÖÁö ¾Ê±â ¶§¹®ÀÌ´Ù.

ppad-1.2.1d¿¡¼­ »ç¿ëÀÚ ÀÎÁõÇÏ´Â code´Â /usr/src/pppd-1.2.1d/pppd/auth.c file¿¡ ÀÖ´Ù.

´ÙÀ½ code´Â #include Áö½ÃÀÚ°¡ À§Ä¡ÇÏ´Â fileÀÇ À­ºÎºÐ¿¡ µ¡´î ÇÊ¿ä°¡ ÀÖ´Ù. ¿ì¸®´Â Á¶°ÇÁö½ÃÀÚ(conditional directive)·Î #include¸¦ µÑ·¯½Õ´Ù (Ưº°È÷ shadow Áö¿ø±â´ÉÀ» ³Ö¾î compileÇÒ ¶§¸¸ Æ÷ÇÔÇϵµ·Ï)


#ifdef HAS_SHADOW
#include <shadow.h>
#include <shadow/pwauth.h>
#endif

´ÙÀ½Àº ½ÇÁ¦ code¸¦ °íÄ¡´Â ÀÏÀÌ´Ù. ¾ÆÁ÷µµ auth.c fileÀ» °íÄ¡°í ÀÖ´Ù.

°íÄ¡±â ÀüÀÇ auth.c´Â:


/*
 * 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);
}

»ç¿ëÀÚ password´Â pw->pw_passwd¿¡ À§Ä¡ÇÑ´Ù. µû¶ó¼­ ÇÒ ÀÏÀº getspnam ÇÔ¼ö¸¦ Ãß°¡ÇÏ´Â °ÍÀÌ ÀüºÎ´Ù. ÀÌ ÇÔ¼ö´Â spwd->sp_pwdp¿¡ password¸¦ ÇÒ´çÇÑ´Ù.

¿ì¸®´Â ´Ù¸¥ ÇöÁ¸ÇÏ´Â(actual) »ç¿ëÀÚ È®ÀÎ ÀÛ¾÷À» ¼öÇàÇϵµ·Ï pwauth ÇÔ¼ö¸¦ ³ÖÀ» °ÍÀÌ´Ù. ÀÌ´Â shadow file¿¡ ¼³Á¤µÇ¾î ÀÖÀ¸¸é ÀÚµ¿ÀûÀ¸·Î µÎ¹ø° ÀÎÁõÀ» ¼öÇàÇÑ´Ù.

shadow¸¦ Áö¿øÇϵµ·Ï °íÄ£ auth.c´Â:


/*
 * 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);
}

ÁÖÀÇÇؼ­ º¸¸é ¿ì¸®°¡ ÇÑ ´Ù¸¥ º¯È­¸¦ º¼ ¼ö ÀÖÀ» °ÍÀÌ´Ù. /etc/passwd file¿¡ password°¡ ¾ø´Ù¸é, ¿ø versionÀº UPAP_AUTHACK¸¦ µ¹·ÁÁÖ°í Á¢¼ÓÀ» Çã¿ëÇß´Ù. ÀÌ°Ç ¾È ÁÁ´Ù. ¿Ö³ÄÇϸé, ÀÌ login±â´ÉÀÇ ÀϹÝÀûÀÎ ¿ëµµ´Â PPP process¿¡ Á¢±ÙÇÑ ´ÙÀ½, PAP¿¡ ÀÇÇØ Áö¿øµÇ´Â »ç¿ëÀÚ À̸§°ú password¸¦ /etc/passwd¿¡ ÀÖ´Â »ç¿ëÀÚ À̸§°ú /etc/shadow¿¡ ÀÖ´Â password¿Í ¸Â´ÂÁö Á¡°ËÇϵµ·Ï Çã¿ëÇÏ´Â, ÇÑ °èÁ¤À» »ç¿ëÇÏ´Â °ÍÀ̱⠶§¹®ÀÌ´Ù.

µû¶ó¼­, ¿ø versionÀÌ »ç¿ëÀÚ(ƯÈ÷, ppp)¸¦ À§ÇØ shellÀ» ½ÇÇà½ÃÅ°µµ·Ï ¼³Á¤Çß´Ù¸é, ´©±¸µçÁö ±×µéÀÇ PAP¸¦ »ç¿ëÀÚÀ̸§À» ppp, password¸¦ null·Î ÇÔÀ¸·Î½á ppp ¿¬°áÀ» ȹµæÇÒ ¼ö ÀÖ¾ú´Ù.

¿ì¸®´Â ÀÌ°ÍÀ» password°¡ ¾ø´Ù¸é UPAP_AUTHACK´ë½Å UPAP_AUTHNAK¸¦ µÇµ¹·ÁÁÖµµ·Ï °íÃÆ´Ù.

Èï¹Ì·Ó°Ôµµ pppd-2.2.0·Î °°Àº ¹®Á¦¸¦ Áö´Ï°í ÀÖ´Ù.

´ÙÀ½Àº µÎ°¡Áö ÀÏÀÌ ÀϾ ¼ö ÀÖµµ·Ï MakefileÀ» °íÁö´Â °ÍÀÌ´Ù: USE_SHADOW°¡ ¼±¾ðµÇ¾î ÀÖ¾î¾ß ÇÏ°í, libshadow.a°¡ linkµÇµµ·Ï ÇÒ ÇÊ¿ä°¡ ÀÖ´Ù.

Makefile¿¡¼­´Â:

LIBS = -lshadow

±×¸®°í³ª¼­ ´ÙÀ½ ÁÙÀ»:

COMPILE_FLAGS = -I.. -D_linux_=1 -DGIDSET_TYPE=gid_t

¿¡¼­:

COMPILE_FLAGS = -I.. -D_linux_=1 -DGIDSET_TYPE=gid_t -DUSE_SHADOW
·Î ¹Ù²Û´Ù.

ÀÌÁ¦ ¸¸µé¾î¼­ ¼³Ä¡Ç϶ó.


ÀÌÀüÆäÀÌÁö ´ÙÀ½ÆäÀÌÁö Â÷·Ê