summaryrefslogblamecommitdiffstats
path: root/main/common/password.c
blob: e149cf468c29c17e8dc6ae97da8202b115ab2c6e (plain) (tree)
1
2
3
4


                                                                           
  































                                                                           
                                          

                 
                                                         

                     
                                  

      

                   



                        



                                


              

                                                                   
  





                                                                   



                        






































                                                                          


                   





                                                                          




                                       
































































































                                                                              


                     


                                                                   



                     
















































                                                                         













                                                                       
               
 

                                
/**************************************************************************
 *
 * Copyright (c) 2013 Alcatel-Lucent
 *
 * Alcatel Lucent licenses this file to You under the Apache License,
 * Version 2.0 (the "License"); you may not use this file except in
 * compliance with the License.  A copy of the License is contained the
 * file LICENSE at the top level of this repository.
 * You may also obtain a copy of the License at:
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 **************************************************************************
 *
 * password:
 *
 * Code that supports the use of a password in the monitor.
 *
 * Original author:     Ed Sutter (ed.sutter@alcatel-lucent.com)
 *
 */
#include "config.h"
#include "stddefs.h"
#include "genlib.h"
#include "ether.h"
#include "tfs.h"
#include "tfsprivate.h"

#if INCLUDE_USRLVL

extern  char *crypt(char *,char *,char *);

/* PASSWORD_FILE:
 *  The name of the file that is used to store passwords.
 */
#ifndef PASSWORD_FILE
#define PASSWORD_FILE   ".monpswd"
#endif

#define SALT0   'T'
#define SALT1   'J'

int
passwordFileExists(void)
{
    if(tfsstat(PASSWORD_FILE)) {
        return(1);
    }
    return(0);
}

/* backdoor():
 *  A mechanism that allows a password to be generated based on the
 *  MAC address of the board...
 *
 *  Return 1 if the password matches the return of crypt(KEY,SALT).
 *  Where:
 *      KEY is an 8-character string created from the MAC address
 *          stored in the ETHERADD environment variable;
 *      SALT is a 2-character string made up of the first and last
 *          character of the ETHERADD env var;
 */
int
backdoor(char *password)
{
    int     i;
    char    *etherstr, salt[3], encryption[32];
    unsigned char etherbin[9];

    etherstr = getenv("ETHERADD");
    if(!etherstr) { /* just in case... */
        etherstr = "00:00:00:00:00:00";
    }

    /* 2 salt characters are the first and last characters of etherstr: */
    salt[0] = etherstr[0];
    salt[1] = etherstr[strlen(etherstr)-1];
    salt[2] = 0;

    EtherToBin(etherstr,etherbin);
    etherbin[6] = 'A';
    etherbin[7] = 'a';
    etherbin[8] = 0;

    for(i=0; i<6; i++) {
        while(etherbin[i] > 0x7e) {
            etherbin[i] -= 0x20;
            etherbin[6]++;
        }
        while(etherbin[i] < 0x20) {
            etherbin[i] += 0x8;
            etherbin[7]++;
        }
    }

    crypt((char *)etherbin,salt,encryption);

    /* Note that the first two characters of the return from crypt() */
    /* are not used in the comparison... */
    if(!strcmp(password,encryption+2)) {
        return(1);
    } else {
        return(0);
    }
}

/* validPassword():
 *  Called with a password and user level.  There are a few different ways
 *  in which this can pass...
 *  1. If there is no PASSWORD_FILE in TFS, return true.
 *  2. If the password matches the backdoor entry, return true.
 *  3. If the password matches appropriate entry in the password file,
 *     return  true.
 */

int
validPassword(char *password, int ulvl)
{
    char    line[80];
    int (*fptr)(void);
    int     tfd, lno, pass, lsize;

    /* If there is a password file, then use it.
     * If there is no password file, then call extValidPassword() to
     * support systems that store the password some other way.
     * The extValidPassword() function should return 0 if password check
     * failed, 1 if the check succeeded and -1 if there is no external
     * password storage hardware.
     * Finally, if there is no password file, AND there is no external
     * password storage hardware, then just return 1 to
     * indicate that ANY password is a valid password.  In other words...
     * the password protection stuff is only enabled if you have a password
     * stored away somewhere.
     */
    if(!passwordFileExists()) {
        static  int warning;

        switch(extValidPassword(password,ulvl)) {
        case 0:         /* Password check failed. */
            return(0);
        case 1:         /* Password check passed. */
            return(1);
        default:        /* No external password check in use. */
            break;
        }
        if(!warning) {
            printf("WARNING: no %s file, security inactive.\n",PASSWORD_FILE);
            warning = 1;
        }
        return(1);
    }

    /* First check for backdoor entry... */
    if(backdoor(password)) {
        return(1);
    }

    /* Incoming user level must be in valid range... */
    if((ulvl < MINUSRLEVEL) || (ulvl > MAXUSRLEVEL)) {
        return(0);
    }

    /* If user level is MINUSRLEVEL, there is no need for a password. */
    if(ulvl == MINUSRLEVEL) {
        return(1);
    }

    /* Check for a match in the password file...
     * The PASSWORD_FILE dedicates one line for each user level.
     * Line1 is password for user level 1.
     * Line2 is password for user level 2.
     * Line3 is password for user level 3.
     * User level 0 doesn't require a password.
     */

    /* Force the getUsrLvl() function to return MAX: */
    fptr = (int(*)(void))setTmpMaxUsrLvl();

    tfd = tfsopen(PASSWORD_FILE,TFS_RDONLY,0);
    if(tfd < 0) {
        /* Restore the original getUsrLvl() functionality: */
        clrTmpMaxUsrLvl(fptr);
        printf("%s\n",(char *)tfsctrl(TFS_ERRMSG,tfd,0));
        return(0);
    }

    lno = 1;
    pass = 0;
    while((lsize=tfsgetline(tfd,line,sizeof(line)))) {
        char    encryption[32], salt[3];

        if(lno != ulvl) {
            lno++;
            continue;
        }

        line[lsize-1] = 0;          /* Remove the newline */

        salt[0] = SALT0;
        salt[1] = SALT1;
        salt[2] = 0;

        crypt(password,salt,encryption);

        if(!strncmp(line,encryption+2,strlen(line)-2)) {
            pass = 1;
        }
        break;
    }
    tfsclose(tfd,0);

    /* Restore the original getUsrLvl() functionality: */
    clrTmpMaxUsrLvl(fptr);

    return(pass);
}

/* newPasswordFile():
 *  Prompt the user for three passwords.  One for each user level.
 *  Then, after retrieving them, make sure the user wants to update
 *  the password file; if yes, do it; else abort.
 */
int
newPasswordFile(void)
{
    int     err, i;
    char    pswd1[16], pswd2[16];
    char    salt[3], *epwp, buf[32], epswd[34*3], flags[8];

    /* For each of the three levels (1,2&3), get the password, encrypt it
     * and concatenate newline for storate into the password file.
     */

    epwp = epswd;
    for(i=1; i<4; i++) {
        while(1) {
            printf("Lvl%d ",i);
            getpass("passwd: ",pswd1,sizeof(pswd1)-1,0);
            if(strlen(pswd1) < 8) {
                printf("password must be >= 8 chars.\n");
                continue;
            }
            getpass("verify: ",pswd2,sizeof(pswd2)-1,0);
            if(strcmp(pswd1,pswd2)) {
                printf("Entries do not match, try again...\n");
            } else {
                break;
            }
        }
        salt[0] = SALT0;
        salt[1] = SALT1;
        salt[2] = 0;
        crypt(pswd1,salt,buf);
        sprintf(epwp,"%s\n",&buf[2]);
        epwp += strlen(epwp);
    }

    if(!askuser("Are you sure?")) {
        return(0);
    }

    err = tfsunlink(PASSWORD_FILE);
    if((err != TFS_OKAY) && (err != TFSERR_NOFILE)) {
        printf("%s\n",(char *)tfsctrl(TFS_ERRMSG,err,0));
        return(-1);
    }

    sprintf(flags,"u%d",MAXUSRLEVEL);
    err = tfsadd(PASSWORD_FILE,0, flags, (uchar *)epswd, strlen(epswd));
    if(err != TFS_OKAY) {
        printf("%s\n",(char *)tfsctrl(TFS_ERRMSG,err,0));
        return(-1);
    }
    return(0);
}


#ifndef EXT_VALID_PASSWORD
/* extValidPassword():
 * See validPassword() above for notes on the purpose of this function.
 *
 * This is the default stub, if a real extValidPassword() function is
 * provided by the port, then EXT_VALID_PASSWORD should be defined in
 * that port's config.h file.
*/
int
extValidPassword(char *password, int ulvl)
{
    return(-1);
}
#endif  /* EXT_VALID_PASSWORD */
#endif  /* INCLUDE_USRLVL */