使用crypt產生使用者密碼-Tested on RedHat & SuSE Platform

來源:互聯網
上載者:User
近期做EasyCluster,需要建立使用者,要求在Linux上能建立一個使用者帳號,很自然想到了背景程式調用useradd命令列來完成,但眾所周 知,密碼是個麻煩事。查看了 useradd的手冊,有個-p password 選項可以在建立的時候就指定密碼,但要求這裡的密碼是已經加過密的,這就要求用crypt函數進行加密,然後再放入命令列。故測試了一下,寫了一段測試代 碼,用來產生密碼:

Code: Select all
#define _XOPEN_SOURCE
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{
    char key[] = "666666";
    printf("encrypted password is: %s\n", crypt(key, "3a"));
    return 0;
}

這 裡就能產生666666的密碼。要注意的是,首先必須定義 _XOPEN_SOURCE ,這是crypt的手冊中要求的;第二,crypt函數的第一個參數是純文字密碼,第二個參數叫做“salt”,其實就是一個加密的密鑰,有兩個字元組成, 字元的取值可以是“a-zA-Z0-9./” 這些,具體請看手冊。

然後用 useradd -p <encrypted password> <username> 就可以產生一個我們指定密碼的帳號了。

CAUTION: 使用者登入和上述過程是一個相反的過程,但難度在於不知道salt。這裡不同的加密方法有不同的規則,比如某些加密方法,加密出來的密文的頭兩個字母就是 salt,有些則不是。在所有的機密方法上,glibc提供了crypt這個調用,屏蔽了多種密碼編譯演算法的複雜性,這應該就是Linux的PAM機制。所 以,使用者登入的時候,首先要根據加密方法在密文中取出salt,然後調用crypt產生密文,再對比,即可!一種加密方法不行,再試第二種。這裡有我們 EasyCluster的使用者登入後台驗證的代碼,在RedHat和SuSE(SuSE和RedHat的加密方法就不同,不過對於建立密碼來說,兩者都是 一樣的,都是調用crypt嘛,如上所述)中都實驗通過了:

Code: Select all
#define _XOPEN_SOURCE
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

#include "easy_s.h"
#include "common.h"

//  you need link your object file like this:
//                        gcc -o xx  xxx.c  -lcrypt
//int authenticate_user(char *username, char *key);

int authenticate_user(char *username, char *key)
{
    const int buffer_len = 512;
    const char filename[50] = "/etc/shadow";
    char *dataline = (char *)malloc(buffer_len);
    if (dataline == NULL){
        message_log("authenticate_user() error: failed to allocate space for user data buffer.");
        return -2;
    }
   
    FILE *fp = fopen(filename, "r");
    if (fp == NULL){
        free(dataline);
        //fprintf(stderr, "failed to open user account file.\n");
        return -1;
    }

    while (fgets(dataline, buffer_len, fp)){
        if (strstr(dataline, username)){   
            /*
    char *crypt(const char *key, const char *salt).
     If  salt is a character string starting with the three characters "$1$"
     followed by at most eight characters, and optionally  terminated 
     by  "$",  then instead of using the DES machine, the glibc crypt
       function uses an MD5-based algorithm,  and  outputs  up  to  34  bytes,
       namely  "$1$<string>$", where "<string>" stands for the up to 8 charac-
       ters following "$1$" in the salt, followed by 22 bytes chosen from  the
       set [a-zA-Z0-9./].
            */
            char *line = strstr(dataline, "$1$");
            char *t;
            /*if ((line == NULL) || (strlen(line) < 4)){
                free(dataline);
                fclose(fp);
                return -4;
            }
            */

            if (line == NULL ){
                line = strchr(dataline, ':');
                if (line == NULL){
                    free(dataline);
                    fclose(fp);
                    return -4;
                }
                t = strchr((line+1), ':');           
                if (t == NULL){
                    free(dataline);
                    fclose(fp);
                    return -4;
                }
                *t = '\0';
                char salt_1[16];
                salt_1[0] = line[1];salt_1[1] = line[2];salt_1[2] = '\0';
                char *pass = crypt(key, salt_1);
                if (pass == NULL){
                    free(dataline);
                    fclose(fp);
                    return -4;
                }
                if (strcmp((line+1), pass) == 0){
                    free(dataline);
                    fclose(fp);
                    return 0;
                }else{
                    free(dataline);
                    fclose(fp);
                    return -5;
                }
            }
            if (strlen(line) < 4){
                free(dataline);
                fclose(fp);
                return -4;
            }
           
            t =strstr((line+3), ":");
            if (t == NULL){
                free(dataline);
                fclose(fp);
                return -4;
            }
            t[0] = '\0';
            t = strstr((line+3), "$");
            if (t == NULL){
                free(dataline);
                fclose(fp);
                return -4;
            }
           
            char salt[50];
            memcpy(salt, line, t-line+1);
            char *encrypt_str = crypt(key, salt);
            if (encrypt_str == NULL){
                free(dataline);
                fclose(fp);
                return -5;
            }
            if (strcmp(encrypt_str, line) == 0){
                free(dataline);
                fclose(fp);
                return 0;
            }
        }
    }

    free(dataline);
    fclose(fp);
    return -4;
}

同上,使用usermod命令的-p選項就可以修改使用者密碼。如:usermod -p <encrypted password> username 即可

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.