
SU                                                              20-MAR-1986 11:11:06    VAX C      V2.1-007                 Page 1
V1.0                                                            13-NOV-1985 09:48:09    DEV:[BODOH.EROS.SU]SU.C;41 (1)



    1        	/*****************************************************************************
    2        	*	SU allows any user who knows the password for SYSTEM to set the SETPRV
    3        	* privilege in their authorized and process privilege masks. Setting the
    4        	* privilege masks requires the privilege CMKRNL, so SU should be installed
    5        	* with CMKRNL. Since SU writes a protected logfile and reads the UAF, it should
    6        	* also be installed with BYPASS.
    7        	*
    8        	*	When SU is run, it first checks to see if the user currently has the
    9        	* SETPRV bit set in their authorized privilege mask. If they do, then;
   10        	*
   11        	*	1) Disable SETPRV in the authorized privilege mask
   12        	*	2) Clear all process privileges (except CMKRNL, cleared in step 4)
   13        	*	3) Sets proc privs to the authorized privs
   14        	*	4) Disable CMKRNL in proc priv if not set in auth priv
   15        	*
   16        	*	If the user does not have SETPRV enabled in their authorized mask;
   17        	*
   18        	* 	1) Prompt them for the password (to SYSTEM)
   19        	*	2) Validate the password (against the UAF)
   20        	*	3) Set SETPRV in the authorized and process privilege masks
   21        	*
   22        	*	Under V4 of VMS, SU will set the DCL prompt to "SU$" which will
   23        	* indicate that the user is in the SuperUser mode.
   24        	******************************************************************************/
   25        	#include descrip
  397        	#include jpidef
  483        	#include stdio
  541        	#include iodef
  814        	#include ssdef
 1223        	#include <stdedc.h>
 1264        	 
 1265        	#define USERCODESZ 32			/* Maximum usercode size	*/
 1266        	#define PWSIZE	40			/* Maximum password size	*/
 1267        	 
 1268        	#define ALLPRIV	-1			/* Mask for all privileges	*/
 1269        	#define	CMKRNL	1			/* Mask for CMKRNL privilege	*/
 1270        	#define SETPRV	16384			/* Mask for SETPRV privilege	*/
 1271        	#define	BYPASS	536870912		/* Mask for BYPASS privilege	*/
 1272        	 
 1273        	struct DESC				/* Define a descriptor structure */
 1274        	{
 1275        		LONG length;
 1276        		TEXT *addr;
 1277        	};
 1278        	 
 1279        		LONG	priv_mask_proc[2];	/* Define global proc priv mask	*/
 1280        		LONG	priv_mask_auth[2];	/* Define global auth priv mask	*/
 1281        		int	set_privs_flag;		/* Flag to set/clear proc privs	*/
 1282        		int	function_flag;		/* Flag to set/clear/get auth privs */
 1283        		int	perm_flag;		/* Flag to indicate priv permanence */
 1284        		FILE	*logfile;		/* Logfile file pointer		*/
 1285        		char	log_comment[30];	/* Comment to write to log	*/
 1286        	 
 1287        	main()
 1288        	{

SU                                                              20-MAR-1986 11:11:06    VAX C      V2.1-007                 Page 2
V1.0                                                            13-NOV-1985 09:48:09    DEV:[BODOH.EROS.SU]SU.C;41 (1)

 1289    1   		LONG	status;			/* General status		    */
 1290    1   		int 	set_clear_privs();
 1291    1   		char	username[USERCODESZ];	/* Place to stash "SYSTEM" username */
 1292    1   		char	password[PWSIZE];	/* Place to stash "SYSTEM" password */
 1293    1   	 
 1294    1   		/* The following logfile open has to be done here, before we clear
 1295    1   		   the bypass privilege */
 1296    1   		logfile = fopen("SYS$SYSDEVICE:[SYS0.SYSMGR]SU.LOG","a");
 1297    1   		if (logfile == 0)
 1298    1   			{
 1299    2   			printf ("Unable to access log file \n");
 1300    2   			exit (SS$_NORMAL);
 1301    2   			}
 1302    1   	 
 1303    1   		function_flag = 0;		/* Get current authorized priv mask */
 1304    1   		status = setpriv(&priv_mask_auth[0],&function_flag);
 1305    1   		if (status != 1)
 1306    1   			{
 1307    2   			printf ("Error %d fetching auth privs \n",status);
 1308    2   			strcpy(log_comment,"Err fetching auth privs");
 1309    2   			status = log_it();
 1310    2   			exit (SS$_NORMAL);
 1311    2   			}
 1312    1   		if (priv_mask_auth[0] & SETPRV)	/* Is SETPRV enabled in auth priv?  */
 1313    1   			{
 1314    2   			/* Clear all privs in proc perm mask (except CMKRNL) */
 1315    2   			priv_mask_proc[0] = ALLPRIV - CMKRNL;
 1316    2   			priv_mask_proc[1] = ALLPRIV;
 1317    2   			set_privs_flag = 0;
 1318    2   			perm_flag = 1;
 1319    2   			status = SYS$CMKRNL(set_clear_privs,0);
 1320    2   			if (status != 1)
 1321    2   				{
 1322    3   				printf ("Error %d clearing all proc privs\n",status);
 1323    3   				strcpy(log_comment,"Err clearing proc privs");
 1324    3   				status = log_it();
 1325    3   				exit (SS$_NORMAL);
 1326    3   				}
 1327    2   	 
 1328    2   			/* Set process permanent privileges to authorized privileges */
 1329    2   			priv_mask_proc[0] = priv_mask_auth[0] - SETPRV;
 1330    2   			priv_mask_proc[1] = priv_mask_auth[1];
 1331    2   			set_privs_flag = 1;
 1332    2   			perm_flag = 1;
 1333    2   			status = SYS$CMKRNL(set_clear_privs,0);
 1334    2   			if (status != 1)
 1335    2   				{
 1336    3   				printf ("Error %d setting proc privs \n",status);
 1337    3   				strcpy(log_comment,"Err setting proc privs");
 1338    3   				status = log_it();
 1339    3   				exit (SS$_NORMAL);
 1340    3   				}
 1341    2   	 
 1342    2   			/* Set BYPASS, CMKRNL in temporary image priv mask	*/
 1343    2   			priv_mask_proc[0] = CMKRNL + BYPASS;
 1344    2   			priv_mask_proc[1] = 0;
 1345    2   			set_privs_flag = 1;

SU                                                              20-MAR-1986 11:11:06    VAX C      V2.1-007                 Page 3
V1.0                                                            13-NOV-1985 09:48:09    DEV:[BODOH.EROS.SU]SU.C;41 (1)

 1346    2   			perm_flag = 0;
 1347    2   			status = SYS$CMKRNL(set_clear_privs,0);
 1348    2   			if (status != 1)
 1349    2   				{
 1350    3   				printf ("Error %d setting temp privs \n",status);
 1351    3   				strcpy(log_comment,"Err setting temp privs");
 1352    3   				status = log_it();
 1353    3   				exit (SS$_NORMAL);
 1354    3   				}
 1355    2   	 
 1356    2   			/* Clear SETPRV in authorized privileges mask */
 1357    2   			function_flag = 1;
 1358    2   			status = setpriv(&priv_mask_auth[0],&function_flag);
 1359    2   			if (status != 1)
 1360    2   				{
 1361    3   				printf ("Error %d clearing auth SETPRV \n",status);
 1362    3   				strcpy(log_comment,"Err clearing auth SETPRV");
 1363    3   				status = log_it();
 1364    3   				exit (SS$_NORMAL);
 1365    3   				}
 1366    2   	 
 1367    2   			/* Clear CMKRNL in proc priv if not in auth priv */
 1368    2   			priv_mask_proc[0] = 0;
 1369    2   			priv_mask_proc[1] = 0;
 1370    2   			if (priv_mask_auth[0] ^ CMKRNL)
 1371    2   				{
 1372    3   				priv_mask_proc[0] = priv_mask_proc[0] + CMKRNL;
 1373    3   				}
 1374    2   			if (priv_mask_proc[0] != 0)
 1375    2   				{
 1376    3   				priv_mask_proc[1] = 0;
 1377    3   				set_privs_flag = 0;
 1378    3   				perm_flag = 1;
 1379    3   				status = SYS$CMKRNL(set_clear_privs,0);
 1380    3   				if (status != 1)
 1381    3   					{
 1382    4   					printf ("Error %d clearing proc CMKRNL \n",
 1383    4   						status);
 1384    4   					strcpy(log_comment,"Err clearing CMKRNL");
 1385    4   					status = log_it();
 1386    4   					exit (SS$_NORMAL);
 1387    4   					}
 1388    3   				}
 1389    2   	 
 1390    2   			strcpy(log_comment,"UNSU");
 1391    2   			status = log_it();
 1392    2   			exit(SS$_NORMAL);		/* We're done !		     */
 1393    2   			}
 1394    1   		
 1395    1   		/* Get password from the user and validate against UAF */
 1396    1   		printf ("Password: ");
 1397    1   		readnoecho(password,20);
 1398    1   		printf ("\n");
 1399    1   		strcpy(username,"SYSTEM "); /* Username to validate	*/
 1400    1   		status = validate(username,password);	/* Validate against UAF	*/
 1401    1   		if (status != 1)
 1402    1   			{

SU                                                              20-MAR-1986 11:11:06    VAX C      V2.1-007                 Page 4
V1.0                                                            13-NOV-1985 09:48:09    DEV:[BODOH.EROS.SU]SU.C;41 (1)

 1403    2   			printf ("Validation error %d logged ! \n",status);
 1404    2   			strcpy(log_comment,"Err validating password");
 1405    2   			status = log_it();
 1406    2   			exit (SS$_NORMAL);
 1407    2   			}
 1408    1   	 
 1409    1   		printf("Enabling SETPRV \n");
 1410    1   	 
 1411    1   		/* Enable SETPRV in authorized priv mask */
 1412    1   		function_flag = 2;
 1413    1   		status = setpriv(&priv_mask_auth[0],&function_flag);
 1414    1   		if (status != 1)
 1415    1   			{
 1416    2   			printf ("Error %d setting auth SETPRV \n",status);
 1417    2   			strcpy(log_comment,"Err setting auth SETPRV");
 1418    2   			status = log_it();
 1419    2   			exit (SS$_NORMAL);
 1420    2   			}
 1421    1   	 
 1422    1   		/* Enable SETPRV in proc priv mask. Cosmetic, but to remind user */
 1423    1   		priv_mask_proc[0] = SETPRV;
 1424    1   		priv_mask_proc[1] = 0;
 1425    1   		set_privs_flag = 1;
 1426    1   		perm_flag = 1;
 1427    1   		status = SYS$CMKRNL(set_clear_privs,0);
 1428    1   		if (status != 1)
 1429    1   			{
 1430    2   			printf ("Error %d setting proc SETPRV \n",status);
 1431    2   			strcpy(log_comment,"Err setting proc SETPRV");
 1432    2   			status = log_it();
 1433    2   			exit (SS$_NORMAL);
 1434    2   			}
 1435    1   	 
 1436    1   		strcpy(log_comment,"SU");
 1437    1   		status = log_it();
 1438    1   	}
 1439        	/* The following routine executes in kernel mode. Fiddling with it could crash
 1440        	the system! */
 1441        	 
 1442        	set_clear_privs(dummy)
 1443        	int dummy;
 1444        		{
 1445    1   		LONG status;
 1446    1   	 
 1447    1   		status = sys$setprv(set_privs_flag,&priv_mask_proc[0],perm_flag,0);
 1448    1   		return(status);
 1449    1   		}
 1450        	 
 1451        	FUNCTION int log_it()
 1452        	{
 1453    1   	int	pidcontext,pid,group,owner,counter;
 1454    1   	LONG	status;
 1455    1   	char	username[12],terminal[5];
 1456    1   	struct DESC opdesc;
 1457    1   	 
 1458    1   	 
 1459    1   	struct outline {

SU                                                              20-MAR-1986 11:11:06    VAX C      V2.1-007                 Page 5
V1.0                                                            13-NOV-1985 09:48:09    DEV:[BODOH.EROS.SU]SU.C;41 (1)

 1460    1   		char carret[1];
 1461    1   		char date[11];
 1462    1   		char space1[1];
 1463    1   		char time[11];
 1464    1   		char space2[1];
 1465    1   		char terminal[5];
 1466    1   		char space3[1];
 1467    1   		char username[12];
 1468    1   		char space4[1];
 1469    1   		char log_comment[31];
 1470    1   	}line;
 1471    1   	 
 1472    1   	struct outline2 {
 1473    1   		char msgtype[1];
 1474    1   		char msgtarg[3];
 1475    1   		int  msgnum;
 1476    1   		char space1[1];
 1477    1   		char lead_in[3];
 1478    1   		char space2[1];
 1479    1   		char username[12];
 1480    1   		char space3[1];
 1481    1   		char terminal[5];
 1482    1   		char space4[1];
 1483    1   		char log_comment[31];
 1484    1   	}opline;
 1485    1   	 
 1486    1   	struct
 1487    1   	{
 1488    1   		short	io_s;
 1489    1   		short	len;
 1490    1   		int	info;
 1491    1   	} iosb;
 1492    1   	 
 1493    1   	struct	ITEM
 1494    1   	{
 1495    1   		short	len;		/* buffer length */
 1496    1   		short	item_code;	/* information item requested */
 1497    1   		char	*buf;		/* return buffer */
 1498    1   		int	*rlen;		/* return length */
 1499    1   	};
 1500    1   	 
 1501    1   	struct
 1502    1   	{
 1503    1   		struct	ITEM items[2];
 1504    1   		int	endoflist;
 1505    1   	} itemlist				=
 1506    1   						{
 1507    1   			/* user name	*/	12,JPI$_USERNAME,username	,0
 1508    1   			/* terminal	*/	,5,JPI$_TERMINAL,terminal	,0
 1509    1   						};
 1510    1   	 
 1511    1   		itemlist.endoflist = 0;
 1512    1   		pidcontext = 0;
 1513    1   		status = sys$getjpi(0,&pidcontext,0,&itemlist,&iosb,0,0);
 1514    1   		if (status != SS$_NORMAL)
 1515    1   			printf("GETJPI status = %d \n",status);
 1516    1   		if (terminal[0] == '\0')

SU                                                              20-MAR-1986 11:11:06    VAX C      V2.1-007                 Page 6
V1.0                                                            13-NOV-1985 09:48:09    DEV:[BODOH.EROS.SU]SU.C;41 (1)

 1517    1   			strncpy(terminal,"     ",5);
 1518    1   	 
 1519    1   		for (counter=0;counter<31;counter++)
 1520    1   			line.log_comment[counter]=32;
 1521    1   		line.carret[0]=32;
 1522    1   		gettim(line.date,line.time);
 1523    1   		strncpy (line.terminal,terminal,5);
 1524    1   		strncpy (line.username,username,12);
 1525    1   		strncpy (line.log_comment,log_comment,30);
 1526    1   		line.log_comment[30]='\n';
 1527    1   		strncpy (line.carret," ",1);	
 1528    1   		strncpy (line.space1," ",1);
 1529    1   		strncpy (line.space2," ",1);
 1530    1   		strncpy (line.space3," ",1);
 1531    1   		strncpy (line.space4," ",1);
 1532    1   		fprintf (logfile,"%s\n",&line);
 1533    1   		fclose(logfile);
 1534    1   	 
 1535    1   	 
 1536    1   		for (counter=0;counter<31;counter++)
 1537    1   			opline.log_comment[counter]=32;
 1538    1   		opline.msgtype[0] = 3;
 1539    1   		opline.msgtarg[0] = 1;
 1540    1   		opline.msgtarg[1] = 0;
 1541    1   		opline.msgtarg[2] = 0;
 1542    1   		opline.msgnum = 0;
 1543    1   		strncpy (opline.lead_in,"SU:",3);
 1544    1   		strncpy (opline.terminal,terminal,5);
 1545    1   		strncpy (opline.username,username,12);
 1546    1   		strncpy (opline.log_comment,log_comment,30);
 1547    1   		opline.log_comment[30]='\0';
 1548    1   		strncpy (opline.space1," ",1);	
 1549    1   		strncpy (opline.space2," ",1);
 1550    1   		strncpy (opline.space3," ",1);
 1551    1   		strncpy (opline.space4," ",1);
 1552    1   		opdesc.addr = &opline;
 1553    1   		opdesc.length = 63;
 1554    1   	/*	status = sys$sndopr(&opdesc,0); */
 1555    1   		if (status != SS$_NORMAL)
 1556    1   			printf("OPMESS error = %d \n",status);
 1557    1   	 
 1558    1   		return(SS$_NORMAL);
 1559    1   	}
 1560        	 
 1561        	LONG LGI$VALIDATE();
 1562        	 
 1563        	struct USERDSC
 1564        	{
 1565        		LONG length;
 1566        		TEXT *tptr;
 1567        	};
 1568        	 
 1569        	FUNCTION BOOL validate(user, pass)
 1570        	 
 1571        		TEXT *user;
 1572        		TEXT *pass;
 1573        	{

SU                                                              20-MAR-1986 11:11:06    VAX C      V2.1-007                 Page 7
V1.0                                                            13-NOV-1985 09:48:09    DEV:[BODOH.EROS.SU]SU.C;41 (1)

 1574    1   	 
 1575    1   		TEXT dummy_UAF[1412];
 1576    1   		struct USERDSC user_d;
 1577    1   		struct USERDSC passwd_d;
 1578    1   		struct USERDSC uaf_d;
 1579    1   		LONG stat;
 1580    1   	 
 1581    1   		user_d.length = strlen(user) - 1;
 1582    1   		passwd_d.length = strlen(pass);
 1583    1   	 
 1584    1   		user_d.tptr = user;
 1585    1   		passwd_d.tptr = pass;
 1586    1   		uaf_d.tptr = dummy_UAF;	
 1587    1   		uaf_d.length = 1412;
 1588    1   	 
 1589    1   		stat = LGI$VALIDATE(&user_d, &passwd_d, &uaf_d);
 1590    1   		if (stat != 1)
 1591    1   			{
 1592    2   			printf("\n status = %d \n",stat);
 1593    2   			return(0);
 1594    2   			}
 1595    1   		else
 1596    1   			return(SS$_NORMAL);
 1597    1   	} 
 1598        	 
 1599        	 
 1600        	FUNCTION readnoecho (buf,size)
 1601        		TEXT *buf;
 1602        		COUNT size;
 1603        	 
 1604        	{
 1605    1   		COUNT chan;
 1606    1   		LONG iosb[2];
 1607    1   		LONG stat,count;
 1608    1   		struct DESC ttdesc;
 1609    1   	 
 1610    1   		ttdesc.addr = "SYS$INPUT";
 1611    1   		ttdesc.length = sizeof("SYS$INPUT") - 1;
 1612    1   	 
 1613    1   		stat = sys$assign(&ttdesc,&chan,0,0,0);
 1614    1   		if (!(stat & 1))
 1615    1   		{
 1616    2   			printf("assign error on SYS$INPUT\n");
 1617    2   			exit(stat);
 1618    2   		}
 1619    1   	      	stat = sys$qiow(3,chan,(IO$_READLBLK | IO$M_NOECHO),iosb,
 1620    1   				0,0,buf,size,0,0,0,0); 
 1621    1   		if (!(stat & 1))
 1622    1   		{
 1623    2   			printf("qio error on SYS$INPUT\n");
 1624    2   			exit(stat);
 1625    2   		}
 1626    1   	 
 1627    1   		for (count=0; count<PWSIZE; count++)
 1628    1   			{
 1629    2   			if (buf[count] == '\r')
 1630    2   				{

SU                                                              20-MAR-1986 11:11:06    VAX C      V2.1-007                 Page 8
V1.0                                                            13-NOV-1985 09:48:09    DEV:[BODOH.EROS.SU]SU.C;41 (1)

 1631    3   				buf[count] = '\0';
 1632    3   				break;
 1633    3   				}
 1634    2   			}
 1635    1   	}
 1636        	 
 1637        	gettim(datstr,timstr)
 1638        	char *datstr;
 1639        	char *timstr;
 1640        		{
 1641    1   		int status;
 1642    1   		char buffer[100];
 1643    1   		struct dsc$descriptor_s timdat;
 1644    1   		timdat.dsc$w_length = 23;
 1645    1   		timdat.dsc$a_pointer = &buffer;
 1646    1   		timdat.dsc$b_class = DSC$K_CLASS_S;
 1647    1   		timdat.dsc$b_dtype = DSC$K_DTYPE_T;
 1648    1   		status = lib$date_time(&timdat);
 1649    1   		strncpy (datstr,&buffer[0],11);
 1650    1   		strncpy (timstr,&buffer[12],11);
 1651    1   		return(0);
 1652    1   		}

 
 
Command Line
------------
 
CC/LIS/NODEB SU

