Chinaunix首页 | 论坛 | 博客
  • 博客访问: 931096
  • 博文数量: 177
  • 博客积分: 8613
  • 博客等级: 中将
  • 技术积分: 2835
  • 用 户 组: 普通用户
  • 注册时间: 2006-03-12 04:16
文章分类
文章存档

2012年(12)

2011年(24)

2010年(24)

2009年(75)

2008年(42)

我的朋友

分类: C/C++

2009-09-02 15:33:39

    8月份除了看postmark.c ,还自己开发了一个自动修改密码、自动发邮件和popo信息的小程序,程序中敏感的地方都删掉了,大体的结构没有改变,像base64编码、urlencode的方法、发邮件的方法等这些函数是完整的,只是涉及到公司业务的给去掉了

#include
#include
#include
#include
#define DEBUG 0
#define MAX_LINE_LENGTH 512
#define COMPLEX_PASS_LEN_MIN 10
#define COMPLEX_PASS_LEN_MAX 12

/* ADT -- linked list
 ** example line in file /etc/userinfo.txt
 ** liufeng:Áõ·å,teh,liufeng@corp.com:woshi@3.com:1:1
 ** define 5 array && 2 value to store these strings .
 */
typedef struct USER {
    char    username[32];
    char    chinese_name[64];
    char    department[32];
    char    email[32];
    char    popo[32];
    int     admin;
    int     modify_pass;
    struct  USER *next;
} userinfo;
typedef struct USERNAME {
    char    username[32];
    struct  USERNAME *next;
} apacheauth ;

userinfo        *userinfo_root;                                 /* head pointer of ADT */
apacheauth      *apacheauth_root;

char const      *userinfo_file =        "/etc/userinfo.txt";
char const      *apache_auth_file =     "/etc/apache.txt";
char const      *normal_log  =          "/tmp/normal_log";
char const      *error_log =            "/tmp/error_log";
char const      *htpasswd =             "/home/apache/bin/htpasswd";
char const      *email_template =       "/etc/email.txt";
char const      *popo_template =        "/etc/popo.txt";
char const      *split  =               ":\n";
char            passwd[COMPLEX_PASS_LEN_MAX+1];
char            passwd_first_str[COMPLEX_PASS_LEN_MAX];
char            passwd_end_3_str[COMPLEX_PASS_LEN_MAX];

FILE            *fp_normal;
FILE            *fp_error;

int generate_complex_passwd( char passwd[] ){
    /* generate a passwd stored it in passwd[]
     ** return 1 if generate suitable string, like:vf^*0Wu4gT
     ** return 0 if generate simple   string, like:BfFicK5X8vS
     */
   
    if( strpbrk(tmp,complex_num) == NULL ||
            strpbrk(tmp,complex_letter) == NULL ||
            strpbrk(tmp,complex_special) == NULL ||
            strstr(tmp,"J8")!=NULL ||
            strstr(tmp,"j8")!=NULL || strstr(tmp,"38")!=NULL ||
            strstr(tmp,"Sb")!=NULL || strstr(tmp,"Sb")!=NULL ||
            strstr(tmp,"sb")!=NULL || strstr(tmp,"SB")!=NULL ){
        if(DEBUG){
            fprintf(fp_normal,"generate simple passwd: %s\n",tmp);
            fflush(fp_normal);
        }
        return 0;
    }

    这个函数是生成复杂密码的,出于安全角度,就不公开了吧,值得注意的是以上在密码中拒绝了那些不好的词汇^_^

}

userinfo *load_file_userinfo(char const *filename)
{
    int             first_time = 1;
    int             error_line_found = 0;
    char            *token;
    char            buffer[MAX_LINE_LENGTH];
    char            tmp[MAX_LINE_LENGTH];
    FILE            *fp;
    userinfo        *root;
    userinfo        *current;
    userinfo        *previous;

    fp = fopen(filename, "r");
    if(fp == NULL){
        perror(filename);
        exit (1);
    }

    while( fgets( buffer, MAX_LINE_LENGTH, fp ) != NULL ) {
        strcpy( tmp, buffer);
        if( *buffer == '#' ){
            continue;
        }

        userinfo *current = (userinfo *)malloc( sizeof( userinfo ) );

        if( (token = strtok(buffer,split) ) != NULL){
            strcpy(current->username, token);
        }
        else { error_line_found = 1; }
        if( ( token = strtok(NULL,split) ) != NULL){
            strcpy(current->chinese_name, token);
        }
        else { error_line_found = 1; }
        if( ( token = strtok(NULL,split) ) != NULL){
            strcpy(current->department, token);
        }
        else { error_line_found = 1; }
        if( ( token = strtok(NULL,split) ) != NULL){
            strcpy(current->email, token);
        }
        else { error_line_found = 1; }
        if( ( token = strtok(NULL,split) ) != NULL){
            strcpy(current->popo, token);
        }
        else { error_line_found = 1; }
        if( ( token = strtok(NULL,split) ) != NULL){
            current->admin = atoi(token);
        }
        else { error_line_found = 1; }
        if( ( token = strtok(NULL,split) ) != NULL){
            current->modify_pass = atoi(token);
        }
        else { error_line_found = 1; }

        if(error_line_found)
        {
            error_line_found = 0;
            free(current);
            fprintf(fp_error, "error line in %s : %s",
                    userinfo_file,tmp);
            fflush(fp_error);
            continue;
        }
        if(DEBUG){
            fprintf(fp_normal, "normal line in %s : %s",
                    userinfo_file,tmp);
            fflush(fp_normal);
        }
        if(first_time){
            first_time = 0;
            root = current;
        }
        else {
            previous->next = current;
        }
        current->next = NULL;
        previous = current;

    }

    return root;

}
apacheauth *load_file_apacheauth(char const *filename)
{
    int             first_time = 1;
    int             error_line_found = 0;
    char            *token;
    char            buffer[MAX_LINE_LENGTH];
    char            tmp[MAX_LINE_LENGTH];
    FILE            *fp;
    apacheauth      *root;
    apacheauth      *current;
    apacheauth      *previous;

    fp = fopen(filename, "r");
    if(fp == NULL){
        perror(filename);
        exit (1);
    }

    while( fgets( buffer, MAX_LINE_LENGTH, fp ) != NULL ) {
        strcpy( tmp, buffer);
        if( *buffer == '#' ){
            continue;
        }

        apacheauth *current = (apacheauth *)malloc( sizeof( apacheauth ) );

        if( (token = strtok(buffer,split) ) != NULL){
            strcpy(current->username, token);
        }
        else { error_line_found = 1; }

        if(error_line_found)
        {
            error_line_found = 0;
            free(current);
            fprintf(fp_error, "error line in %s : %s",
                    apache_auth_file,tmp);
            fflush(fp_error);
            continue;
        }
        if(DEBUG){
            fprintf(fp_normal, "normal line in %s : %s",
                    apache_auth_file,tmp);
            fflush(fp_normal);
        }
        if(first_time){
            first_time = 0;
            root = current;
        }
        else {
            previous->next = current;
        }
        current->next = NULL;
        previous = current;

    }
    return root;

}

int change_passwd(char *username, char *passwd)
{
    char          buffer[MAX_LINE_LENGTH];
    strcpy(buffer,htpasswd);
    strcat(buffer," -b ");
    strcat(buffer,apache_auth_file);
    strcat(buffer," ");
    strcat(buffer,username);
    strcat(buffer," \'");
    strcat(buffer,passwd);
    strcat(buffer,"\'");
    if(DEBUG){
        fprintf(fp_normal,"change passwd str: %s\n",buffer);
        fflush(fp_normal);
    }
    if( system(buffer) != 0 ){
        return 0;
    }

    return 1;

}

int send_email(userinfo *i, char *passwd)
{
    FILE    *fp;
    FILE    *mail;
    char    buffer[MAX_LINE_LENGTH];
    fp = popen("/usr/lib/sendmail -F admin -t","w");
    if( fp == NULL ){
        fprintf(fp_error,"%s\n","popen sendmail failed !");
        return 0;
    }

    mail = fopen(email_template,"r");
    if( mail == NULL ){
        perror(email_template);
        return 0;
    }

    fprintf(fp,"From:svn admin\n");
    fprintf(fp,"To:%s<%s>\n",i->username,i->email);

    while( fgets( buffer, MAX_LINE_LENGTH, mail ) != NULL ){
        if( *buffer == '#' )
            continue;
        //if( strstr(buffer,"$chinese_name") != NULL )
        if( !strcmp(buffer,"$chinese_name\n") )
            strcpy(buffer,i->chinese_name);
        //if( strstr(buffer,"$passwd") != NULL )
        if( !strcmp(buffer,"$passwd\n") )
            strcpy(buffer,passwd);
        fprintf(fp,"%s",buffer);

    }
    pclose(fp);
    return 1;

}

void base64_encode( char *result, char *src )
{
    /*
     ** ---------------- ansi txt file ----------------- /etc/popo.txt
     */
    char const *base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    char buffer[4];
    int j = 0;
    int i;

    int len = strlen( src );
    int remainder = len % 3;

    for(i=0; i        strncpy(buffer,(src+i),3);

        result[j++] = base64[(unsigned char )buffer[0] >> 2];
        result[j++] = base64[( ( (unsigned char ) buffer[0] & 0x3) << 4 ) | ( (unsigned char )buffer[1] >> 4)];
        result[j++] = base64[( ( (unsigned char )buffer[1] & 0xf ) << 2 ) | ( (unsigned char )buffer[2] >> 6 )];
        result[j++] = base64[( (unsigned char )buffer[2] & 0x3f )];
    }
    result[j] = '\0';
    if(remainder){
        if( result[j-1] == 'A' ) {
            result[j-1] = '=';
            if( result[j-2] == 'A' ){
                result[j-2] = '=';
                //if( result[j-3] == 'A' ) result[j-3] = '=';

            }

        }

    }

}

void url_encode( char *result, char *src )
{
    //char *standard = "-_.0123456789abcdefghijklmnopqrstuvwxyz";
    char *standard = "-_.0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    //char *src = "x+s=";
    char tmp[4];
    tmp[0] = '\0';
    result[0] = '\0';

    while( *src != '\0' ){
        if( strchr( standard, *src ) != NULL ){
            strncat(result,src,1);
        }
        else{
            sprintf( tmp,"%%%0x",*src );
            strcat(result,tmp);
        }              
        src++;
    }

}

void send_popo(userinfo *i, char *passwd)
{
    FILE *fp;
    char file_messages[2048];
    char base64_messages[2048];
    char url_encode_messages[2048];
    char popo_messages[2048+150];
    char buffer[MAX_LINE_LENGTH];


    fp = fopen(popo_template,"r");
    if( fp == NULL ){
        perror(popo_template);
        exit (1);
    }
    while( fgets( buffer, MAX_LINE_LENGTH, fp ) != NULL ){
        if( *buffer == '#' )
            continue;
        if( !strcmp(buffer,"$passwd\n") )
            strcpy(buffer,passwd);
        strcat(file_messages,buffer);
        strcat(file_messages,"\r\n");
    }
    base64_encode( base64_messages, file_messages );
    url_encode( url_encode_messages, base64_messages );
    /*
     ** example
     */
    sprintf(popo_messages,"/usr/bin/wget -O /tmp/re \"%s&%s\"",i->popo,url_encode_messages);
    //printf("%s\n",popo_messages);
    system(popo_messages);

}

int main(void)
{

    char buffer[MAX_LINE_LENGTH];

    fp_normal = fopen(normal_log,"w");
    if(fp_normal == NULL){
        perror(normal_log);
        exit (1);
    }

    fp_error = fopen(error_log,"w");
    if(fp_error == NULL){
        perror(error_log);
        exit (1);
    }

    /* store username to single linked list in 2 files */
    userinfo_root = load_file_userinfo( userinfo_file );
    apacheauth_root = load_file_apacheauth( apache_auth_file );

    /* compare the 2 files to find any error in files and log it */
    apacheauth      *j;
    userinfo        *i;
    for( j=apacheauth_root; j; j=j->next ){
        for(i=userinfo_root; i; i=i->next){
            if( !strcmp(i->username,j->username) )
                break;
        }
        if( i == NULL ){
            fprintf( fp_error,"%s in file %s, but not in file %s , must modify by hand !\n",
                    j->username,apache_auth_file,userinfo_file );
            fflush(fp_error);
        }

    }

    for(i=userinfo_root; i; i=i->next){
        for( j=apacheauth_root; j; j=j->next ){
            if( !strcmp(i->username,j->username) )
                break;
        }
        if( j == NULL ){
            i->modify_pass = 0;
            fprintf( fp_error,"%s in file %s, but not in file %s , can not modify his passwd !\n",
                    i->username,userinfo_file,apache_auth_file );
            fflush(fp_error);
        }

    }

    srand( time(NULL) );
    //srand( 40 );
    for( i=userinfo_root; i; i=i->next ){
        if(!i->modify_pass){
            if(DEBUG){
                fprintf(fp_normal,"did not change passwd for username: %s\n",i->username);
                fflush(fp_normal);
            }
            continue;
        }
        while( !generate_complex_passwd(passwd) ){
            ;
        }
        strncpy( passwd_first_str, passwd, (strlen(passwd)-3) );
        strcpy( passwd_end_3_str, ( passwd+strlen(passwd)-3 ) );
        if( DEBUG ){
            fprintf(fp_normal, "username:%s passwd:%s email_str:%s popo_str:%s\n",
                    i->username,passwd,passwd_first_str,passwd_end_3_str);
            fflush(fp_normal);
        }

        if( !change_passwd( i->username, passwd ) ){
            fprintf(fp_error,"change passwd fail for username: %s\n",i->username);
            fflush(fp_error);
        }
        else {
            if(DEBUG){
                fprintf(fp_normal,"change passwd success for username: %s\n",i->username);
                fflush(fp_normal);
            }
        }

        if( !send_email( i, passwd_first_str ) ){
            fprintf(fp_error,"sendmail fail for username: %s\n",i->username);
            fflush(fp_error);
        }

        send_popo( i, passwd_end_3_str );
    }

}


总结一下,这个程序使用了:
1、文件操作,包括读写文件;
2、简单的单链表操作,最后应该释放内存的,我也没有释放;
3、base64编码,这个编码费了10天的劲才弄出来,关键点是那个unsigned char  不理解不行啊,在搞这个的过程中学了很多关于编码的知识;
4、urlencode的方法,这个比较简单,我用strcat和sprintf拼接字符串做到,没有用移位取十六进制的方式,感觉这样比较好点;
5、非常重要的,逻辑流程,刚开始的一周都在做计划,怎么做怎么做,结果还是开始的时候大动了好几次。
阅读(681) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~