User Levels

User Levels

As discussed earlier, MicroMonitors CLI could also be accessible to the user interface of the application which is good and bad. Making the CLI accessible to applications is good because it keeps MicroMonitor accessible when the application is up. Developers can therefore do some bare metal stuff at the application command line without having to build additional features into the application. However, making the MicroMonitor CLI accessible to the application also makes it accessible to an end user. This means that the end user could modify RAM, erase flash memory, edit/remove files from TFS, and take other drastic actions that can have a permanent effect on the system. If you are worried about a user getting control of the system, the easiest solution is to just not enable the hook that allows the MicroMonitor commands to be accessible through the application; however, this eliminates the ability to use the monitor CLI from application space.

To mitigate some of these risks, MicroMonitor supports user levels, allowing each command to be configured so that it can only be run at or above a particular user level. If the application is running at a user level below the level required to access a MicroMonitor command, the user cannot access the command through the application. User-level functionality provides flexibility and is simple to add to the CLI.

Implementing user-level security requires some way to store a configurable user level for each command, plus a password facility. I chose to store the user level for each command in an array that parallels the command table array. Note that this array is separate from the command table because the command table array in ROM and this array must be in RAM, and, in MicroMonitor, I assume there is no writable initialized data. The declaration looks like this

 char cmdUlvl[(sizeof(cmdlist)/sizeof(struct monCommand))]; 

The number of entries in this table matches the number of entries in the command table, so this and the command table can be indexed similarly. If the third command in the cmdlist[] table is add , the required user level to execute the add command is stored in the third element of the cmdUlvl table. I can include user-level functionality with the command line processor by adding a few more lines to the docommand() function (see Listing 5.13). The getUsrLvl() function simply returns the current user level of the system. Pointer arithmetic is used to determine what the index into the cmdUlvl[] array needs to be, and that index value is compared to the return value of getUsrLvl() .

Listing 5.13: Adding User Levels to docommand().
image from book
 ...     cmdptr = cmdlist;     while(cmdptr->name) {         if (strcmp(argv[0],cmdptr->name) == 0)             break;         cmdptr++;     }     if (cmdptr->name) {         if (cmdUlvl[cmdptr-cmdlist] > getUsrLvl()) {             printf("User-level access denied.\n");             return(CMD_ULVL_DENIED);         }         ret = cmdptr->func(argc,argv);     }     ... 
image from book
 

By default, the user level for each command is set to zero, and MicroMonitor itself runs at level three. A higher user level means more privileges, so the default behavior is for all commands to be accessible. A MicroMonitor command, ulvl , allows the user to re-configure both the monitors running user level and the user level required to access each of the commands. Stepping down to a lower user level is granted without challenge. Stepping up to a higher user level requires a password. Because the monitor has four user levels, the system needs three passwords. (Level 0 does not require a password.) The ulvl command handles administration of the password file. The password file is always stored at the highest user level, so the password file is inaccessible to all user levels below user level three. Files in the flash file system can also be stored with a password based on user level. (See "User Levels" on page 140 of Chapter 7.)

Listing 5.14 shows the code used to set up a commands user level. The input is a comma-delimited string containing the command name followed by the requested user level.

Listing 5.14: Setting Up the User Level for a Command.
image from book
 int setCmdUlvl(char *cmdandlevel, int verbose) {     struct monCommand *cptr;     int newlevel, idx;     char *comma;     /* First verify that the comma is in the string... */     comma = strchr(cmdandlevel,',');     if (!comma)         goto showerr;     /* Retrieve and verify the new level to be assigned... */     newlevel = atoi(comma+1);     if ((newlevel < MINUSRLEVEL)  (newlevel > MAXUSRLEVEL))         goto showerr;     *comma = 0;     /* Don't allow adjustment of the ulvl command itself.      *  It must be able to run as user level 0 all the time...      */     if (!strcmp(cmdandlevel, ULVLCMD))     {         printf("Can't adjust '%s' user level.\n", ULVLCMD);         return(-1);     }     /* Find the command in the table that is to be adjusted...      */     for(idx=0,cptr=cmdlist;cptr->name;cptr++,idx++)     {         if (!strcmp(cmdandlevel, cptr->name))         {             /* If the command's user level is to be lowered, then              * the current monitor user level must be at least as              * high as the command's current user level...              */             if ((newlevel < cmdUlvl[idx]) &&                 (getUsrLvl() < cmdUlvl[idx]))             {                 if (verbose)                     printf("Ulvl failed: %s\n", cmdandlevel);                 return(1);             }             cmdUlvl[idx] = newlevel;             return(0);         }     } showerr:     if (verbose)         printf("Input error: %s\n", cmdandlevel);     return(-1); } 
image from book
 

Notice that the ulvl command itself cannot have its user level changed. It must always be accessible without the need for a password. Otherwise you could trap yourself by making the ulvl command a level three command, then lowering the user level to two. After the levels were changed, there would be no way to get to level three again, because you must already be at level three to use the ulvl command. Forcing the ulvl command to stay at level zero eliminates this catch-22.



Embedded Systems Firmware Demystified
Embedded Systems Firmware Demystified (With CD-ROM)
ISBN: 1578200997
EAN: 2147483647
Year: 2002
Pages: 118
Authors: Ed Sutter

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net