Exemple #1
0
int main(int argc, char **argv)
{
    FILE *fp;
    // Bucket to keep pids in.
    int process_pool[POOL_SIZE];
    // Count of pids we are wait()ing on.
    int c = 0, test_config = 0, use_ip_address = 0, pid = 0, status, i = 0, active_processes = 0;
    int gid = 0, client_sock = 0, sock = 0, port = DEFAULT_PORT, ret = 0;
    char *dir  = DEFAULTDIR;
    char *group = GROUPGLOBAL;
    char *server_cert = NULL;
    char *server_key = NULL;
    char *ca_cert = NULL;
    char buf[4096 +1];
    SSL_CTX *ctx;
    SSL *ssl;
    char srcip[IPSIZE +1];
    struct sockaddr_in _nc;
    socklen_t _ncl;


    /* Initializing some variables */
    memset(srcip, '\0', IPSIZE + 1);
    memset(process_pool, 0x0, POOL_SIZE);

    bio_err = 0;


    /* Setting the name */
    OS_SetName(ARGV0);
    /* add an option to use the ip on the socket to tie the name to a
       specific address */
    while((c = getopt(argc, argv, "Vdhtig:D:m:p:v:x:k:")) != -1)
    {
        switch(c){
            case 'V':
                print_version();
                break;
            case 'h':
                help_authd();
                break;
            case 'd':
                nowDebug();
                break;
            case 'i':
                use_ip_address = 1;
                break;
            case 'g':
                if(!optarg)
                    ErrorExit("%s: -g needs an argument",ARGV0);
                group = optarg;
                break;
            case 'D':
                if(!optarg)
                    ErrorExit("%s: -D needs an argument",ARGV0);
                dir = optarg;
                break;
            case 't':
                test_config = 1;
                break;
            case 'p':
               if(!optarg)
                    ErrorExit("%s: -%c needs an argument",ARGV0, c);
                port = atoi(optarg);
                if(port <= 0 || port >= 65536)
                {
                    ErrorExit("%s: Invalid port: %s", ARGV0, optarg);
                }
                break;
            case 'v':
                if (!optarg)
                    ErrorExit("%s: -%c needs an argument", ARGV0, c);
                ca_cert = optarg;
                break;
            case 'x':
                if (!optarg)
                    ErrorExit("%s: -%c needs an argument", ARGV0, c);
                server_cert = optarg;
                break;
            case 'k':
                if (!optarg)
                    ErrorExit("%s: -%c needs an argument", ARGV0, c);
                server_key = optarg;
                break;
            default:
                help_authd();
                break;
        }

    }

    /* Starting daemon -- NB: need to double fork and setsid */
    debug1(STARTED_MSG,ARGV0);

    /* Check if the user/group given are valid */
    gid = Privsep_GetGroup(group);
    if(gid < 0)
        ErrorExit(USER_ERROR,ARGV0,"",group);


    /* Exit here if test config is set */
    if(test_config)
        exit(0);


    /* Privilege separation */
    if(Privsep_SetGroup(gid) < 0)
        ErrorExit(SETGID_ERROR,ARGV0,group);


    /* chrooting -- TODO: this isn't a chroot. Should also close
       unneeded open file descriptors (like stdin/stdout)*/
    chdir(dir);



    /* Signal manipulation */
    StartSIG(ARGV0);


    /* Creating PID files */
    if(CreatePID(ARGV0, getpid()) < 0)
        ErrorExit(PID_ERROR,ARGV0);

    /* Start up message */
    verbose(STARTUP_MSG, ARGV0, (int)getpid());


    fp = fopen(KEYSFILE_PATH,"a");
    if(!fp)
    {
        merror("%s: ERROR: Unable to open %s (key file)", ARGV0, KEYSFILE_PATH);
        exit(1);
    }


    /* Starting SSL */
    ctx = os_ssl_keys(1, dir, server_cert, server_key, ca_cert);
    if(!ctx)
    {
        merror("%s: ERROR: SSL error. Exiting.", ARGV0);
        exit(1);
    }


    /* Connecting via TCP */
    sock = OS_Bindporttcp(port, NULL, 0);
    if(sock <= 0)
    {
        merror("%s: Unable to bind to port %d", ARGV0, port);
        exit(1);
    }
    fcntl(sock, F_SETFL, O_NONBLOCK);

    debug1("%s: DEBUG: Going into listening mode.", ARGV0);
    while(1)
    {

        // no need to completely pin the cpu, 100ms should be fast enough
        usleep(100*1000);

        // Only check process-pool if we have active processes
        if(active_processes > 0){
            for (i = 0; i < POOL_SIZE; i++)
            {
                int rv = 0;
                status = 0;
                if (process_pool[i])
                {
                    rv = waitpid(process_pool[i], &status, WNOHANG);
                    if (rv != 0){
                        debug1("%s: DEBUG: Process %d exited", ARGV0, process_pool[i]);
                        process_pool[i] = 0;
                        active_processes = active_processes - 1;
                    }
                }
            }
        }
        memset(&_nc, 0, sizeof(_nc));
        _ncl = sizeof(_nc);

        if((client_sock = accept(sock, (struct sockaddr *) &_nc, &_ncl)) > 0){
            if (active_processes >= POOL_SIZE)
            {
                merror("%s: Error: Max concurrency reached. Unable to fork", ARGV0);
                break;
            }
            pid = fork();
            if(pid)
            {
                active_processes = active_processes + 1;
                close(client_sock);
                for (i = 0; i < POOL_SIZE; i++)
                {
                    if (! process_pool[i])
                    {
                        process_pool[i] = pid;
                        break;
                    }
                }
            }
            else
            {
                strncpy(srcip, inet_ntoa(_nc.sin_addr),IPSIZE -1);
                char *agentname = NULL;
                ssl = SSL_new(ctx);
                SSL_set_fd(ssl, client_sock);

                do
                {
                    ret = SSL_accept(ssl);

                    if (ssl_error(ssl, ret))
                        clean_exit(ctx, client_sock);

                } while (ret <= 0);

                verbose("%s: INFO: New connection from %s", ARGV0, srcip);

                do
                {
                    ret = SSL_read(ssl, buf, sizeof(buf));

                    if (ssl_error(ssl, ret))
                        clean_exit(ctx, client_sock);

                } while (ret <= 0);

                int parseok = 0;
                if(strncmp(buf, "OSSEC A:'", 9) == 0)
                {
                    char *tmpstr = buf;
                    agentname = tmpstr + 9;
                    tmpstr += 9;
                    while(*tmpstr != '\0')
                    {
                        if(*tmpstr == '\'')
                        {
                            *tmpstr = '\0';
                            verbose("%s: INFO: Received request for a new agent (%s) from: %s", ARGV0, agentname, srcip);
                            parseok = 1;
                            break;
                        }
                        tmpstr++;
                    }
                }
                if(parseok == 0)
                {
                    merror("%s: ERROR: Invalid request for new agent from: %s", ARGV0, srcip);
                }
                else
                {
                    int acount = 2;
                    char fname[2048 +1];
                    char response[2048 +1];
                    char *finalkey = NULL;
                    response[2048] = '\0';
                    fname[2048] = '\0';
                    if(!OS_IsValidName(agentname))
                    {
                        merror("%s: ERROR: Invalid agent name: %s from %s", ARGV0, agentname, srcip);
                        snprintf(response, 2048, "ERROR: Invalid agent name: %s\n\n", agentname);
                        ret = SSL_write(ssl, response, strlen(response));
                        snprintf(response, 2048, "ERROR: Unable to add agent.\n\n");
                        ret = SSL_write(ssl, response, strlen(response));
                        sleep(1);
                        exit(0);
                    }


                    /* Checking for a duplicated names. */
                    strncpy(fname, agentname, 2048);
                    while(NameExist(fname))
                    {
                        snprintf(fname, 2048, "%s%d", agentname, acount);
                        acount++;
                        if(acount > 256)
                        {
                            merror("%s: ERROR: Invalid agent name %s (duplicated)", ARGV0, agentname);
                            snprintf(response, 2048, "ERROR: Invalid agent name: %s\n\n", agentname);
                            ret = SSL_write(ssl, response, strlen(response));
                            snprintf(response, 2048, "ERROR: Unable to add agent.\n\n");
                            ret = SSL_write(ssl, response, strlen(response));
                            sleep(1);
                            exit(0);
                        }
                    }
                    agentname = fname;


                    /* Adding the new agent. */
                    if (use_ip_address)
                    {
                        finalkey = OS_AddNewAgent(agentname, srcip, NULL, NULL);
                    }
                    else
                    {
                        finalkey = OS_AddNewAgent(agentname, NULL, NULL, NULL);
                    }
                    if(!finalkey)
                    {
                        merror("%s: ERROR: Unable to add agent: %s (internal error)", ARGV0, agentname);
                        snprintf(response, 2048, "ERROR: Internal manager error adding agent: %s\n\n", agentname);
                        ret = SSL_write(ssl, response, strlen(response));
                        snprintf(response, 2048, "ERROR: Unable to add agent.\n\n");
                        ret = SSL_write(ssl, response, strlen(response));
                        sleep(1);
                        exit(0);
                    }


                    snprintf(response, 2048,"OSSEC K:'%s'\n\n", finalkey);
                    verbose("%s: INFO: Agent key generated for %s (requested by %s)", ARGV0, agentname, srcip);
                    ret = SSL_write(ssl, response, strlen(response));
                    if(ret < 0)
                    {
                        merror("%s: ERROR: SSL write error (%d)", ARGV0, ret);
                        merror("%s: ERROR: Agen key not saved for %s", ARGV0, agentname);
                        ERR_print_errors_fp(stderr);
                    }
                    else
                    {
                        verbose("%s: INFO: Agent key created for %s (requested by %s)", ARGV0, agentname, srcip);
                    }
                }

                clean_exit(ctx, client_sock);
            }
        }
    }


    /* Shutdown the socket */
    clean_exit(ctx, sock);

    return (0);
}
Exemple #2
0
int main(int argc, char **argv)
{
    FILE *fp;
    char *authpass = NULL;
    /* Bucket to keep pids in */
    int process_pool[POOL_SIZE];
    /* Count of pids we are wait()ing on */
    int c = 0, test_config = 0, use_ip_address = 0, pid = 0, status, i = 0, active_processes = 0;
    int use_pass = 1;
    int force_antiquity = -1;
    char *id_exist;
    gid_t gid;
    int client_sock = 0, sock = 0, port = DEFAULT_PORT, ret = 0;
    const char *dir  = DEFAULTDIR;
    const char *group = GROUPGLOBAL;
    const char *server_cert = NULL;
    const char *server_key = NULL;
    const char *ca_cert = NULL;
    char buf[4096 + 1];
    SSL_CTX *ctx;
    SSL *ssl;
    char srcip[IPSIZE + 1];
    struct sockaddr_in _nc;
    socklen_t _ncl;

    /* Initialize some variables */
    memset(srcip, '\0', IPSIZE + 1);
    memset(process_pool, 0x0, POOL_SIZE * sizeof(*process_pool));
    bio_err = 0;

    /* Set the name */
    OS_SetName(ARGV0);

    while ((c = getopt(argc, argv, "Vdhtig:D:m:p:v:x:k:nf:")) != -1) {
        char *end;

        switch (c) {
            case 'V':
                print_version();
                break;
            case 'h':
                help_authd();
                break;
            case 'd':
                nowDebug();
                break;
            case 'i':
                use_ip_address = 1;
                break;
            case 'g':
                if (!optarg) {
                    ErrorExit("%s: -g needs an argument", ARGV0);
                }
                group = optarg;
                break;
            case 'D':
                if (!optarg) {
                    ErrorExit("%s: -D needs an argument", ARGV0);
                }
                dir = optarg;
                break;
            case 't':
                test_config = 1;
                break;
            case 'n':
                use_pass = 0;
                break;
            case 'p':
                if (!optarg) {
                    ErrorExit("%s: -%c needs an argument", ARGV0, c);
                }
                port = atoi(optarg);
                if (port <= 0 || port >= 65536) {
                    ErrorExit("%s: Invalid port: %s", ARGV0, optarg);
                }
                break;
            case 'v':
                if (!optarg) {
                    ErrorExit("%s: -%c needs an argument", ARGV0, c);
                }
                ca_cert = optarg;
                break;
            case 'x':
                if (!optarg) {
                    ErrorExit("%s: -%c needs an argument", ARGV0, c);
                }
                server_cert = optarg;
                break;
            case 'k':
                if (!optarg) {
                    ErrorExit("%s: -%c needs an argument", ARGV0, c);
                }
                server_key = optarg;
                break;
            case 'f':
                if (!optarg)
                    ErrorExit("%s: -%c needs an argument", ARGV0, c);

                force_antiquity = strtol(optarg, &end, 10);

                if (optarg == end || force_antiquity < 0)
                    ErrorExit("%s: Invalid number for -f", ARGV0);

                break;
            default:
                help_authd();
                break;
        }
    }

    /* Start daemon -- NB: need to double fork and setsid */
    debug1(STARTED_MSG, ARGV0);

    /* Check if the user/group given are valid */
    gid = Privsep_GetGroup(group);
    if (gid == (gid_t) - 1) {
        ErrorExit(USER_ERROR, ARGV0, "", group);
    }

    /* Exit here if test config is set */
    if (test_config) {
        exit(0);
    }

    /* Privilege separation */
    if (Privsep_SetGroup(gid) < 0) {
        ErrorExit(SETGID_ERROR, ARGV0, group, errno, strerror(errno));
    }

    /* chroot -- TODO: this isn't a chroot. Should also close
     * unneeded open file descriptors (like stdin/stdout)
     */
    if (chdir(dir) == -1) {
        ErrorExit(CHDIR_ERROR, ARGV0, dir, errno, strerror(errno));
    }

    /* Signal manipulation */
    StartSIG(ARGV0);

    /* Create PID files */
    if (CreatePID(ARGV0, getpid()) < 0) {
        ErrorExit(PID_ERROR, ARGV0);
    }

    /* Start up message */
    verbose(STARTUP_MSG, ARGV0, (int)getpid());

    if (use_pass) {

        /* Checking if there is a custom password file */
        fp = fopen(AUTHDPASS_PATH, "r");
        buf[0] = '\0';
        if (fp) {
            buf[4096] = '\0';
            char *ret = fgets(buf, 4095, fp);

            if (ret && strlen(buf) > 2) {
                /* Remove newline */
                buf[strlen(buf) - 1] = '\0';
                authpass = strdup(buf);
            }

            fclose(fp);
        }

        if (buf[0] != '\0')
            verbose("Accepting connections. Using password specified on file: %s",AUTHDPASS_PATH);
        else {
            /* Getting temporary pass. */
            authpass = __generatetmppass();
            verbose("Accepting connections. Random password chosen for agent authentication: %s", authpass);
        }
    } else
        verbose("Accepting insecure connections. No password required (not recommended)");

    /* Getting SSL cert. */

    fp = fopen(KEYSFILE_PATH, "a");
    if (!fp) {
        merror("%s: ERROR: Unable to open %s (key file)", ARGV0, KEYSFILE_PATH);
        exit(1);
    }
    fclose(fp);

    /* Start SSL */
    ctx = os_ssl_keys(1, dir, server_cert, server_key, ca_cert);
    if (!ctx) {
        merror("%s: ERROR: SSL error. Exiting.", ARGV0);
        exit(1);
    }

    /* Connect via TCP */
    sock = OS_Bindporttcp(port, NULL, 0);
    if (sock <= 0) {
        merror("%s: Unable to bind to port %d", ARGV0, port);
        exit(1);
    }

    fcntl(sock, F_SETFL, O_NONBLOCK);
    debug1("%s: DEBUG: Going into listening mode.", ARGV0);

    /* Setup random */
    srandom_init();

    /* Chroot */
    if (Privsep_Chroot(dir) < 0)
        ErrorExit(CHROOT_ERROR, ARGV0, dir, errno, strerror(errno));

    nowChroot();

    while (1) {
        /* No need to completely pin the cpu, 100ms should be fast enough */
        usleep(100 * 1000);

        /* Only check process-pool if we have active processes */
        if (active_processes > 0) {
            for (i = 0; i < POOL_SIZE; i++) {
                int rv = 0;
                status = 0;
                if (process_pool[i]) {
                    rv = waitpid(process_pool[i], &status, WNOHANG);
                    if (rv != 0) {
                        debug1("%s: DEBUG: Process %d exited", ARGV0, process_pool[i]);
                        process_pool[i] = 0;
                        active_processes = active_processes - 1;
                    }
                }
            }
        }
        memset(&_nc, 0, sizeof(_nc));
        _ncl = sizeof(_nc);

        if ((client_sock = accept(sock, (struct sockaddr *) &_nc, &_ncl)) > 0) {
            if (active_processes >= POOL_SIZE) {
                merror("%s: Error: Max concurrency reached. Unable to fork", ARGV0);
                break;
            }
            pid = fork();
            if (pid) {
                active_processes = active_processes + 1;
                close(client_sock);
                for (i = 0; i < POOL_SIZE; i++) {
                    if (! process_pool[i]) {
                        process_pool[i] = pid;
                        break;
                    }
                }
            } else {
                strncpy(srcip, inet_ntoa(_nc.sin_addr), IPSIZE - 1);
                char *agentname = NULL;
                ssl = SSL_new(ctx);
                SSL_set_fd(ssl, client_sock);

                do {
                    ret = SSL_accept(ssl);

                    if (ssl_error(ssl, ret)) {
                        clean_exit(ctx, client_sock);
                    }

                } while (ret <= 0);
                verbose("%s: INFO: New connection from %s", ARGV0, srcip);
                buf[0] = '\0';

                do {
                    ret = SSL_read(ssl, buf, sizeof(buf));

                    if (ssl_error(ssl, ret)) {
                        clean_exit(ctx, client_sock);
                    }

                } while (ret <= 0);

                int parseok = 0;
                char *tmpstr = buf;

                /* Checking for shared password authentication. */
                if(authpass) {
                    /* Format is pretty simple: OSSEC PASS: PASS WHATEVERACTION */
                    if (strncmp(tmpstr, "OSSEC PASS: "******"%s: ERROR: Invalid password provided by %s. Closing connection.", ARGV0, srcip);
                        SSL_CTX_free(ctx);
                        close(client_sock);
                        exit(0);
                    }
                }

                /* Checking for action A (add agent) */
                parseok = 0;
                if (strncmp(tmpstr, "OSSEC A:'", 9) == 0) {
                    agentname = tmpstr + 9;
                    tmpstr += 9;
                    while (*tmpstr != '\0') {
                        if (*tmpstr == '\'') {
                            *tmpstr = '\0';
                            verbose("%s: INFO: Received request for a new agent (%s) from: %s", ARGV0, agentname, srcip);
                            parseok = 1;
                            break;
                        }
                        tmpstr++;
                    }
                }
                if (parseok == 0) {
                    merror("%s: ERROR: Invalid request for new agent from: %s", ARGV0, srcip);
                } else {
                    int acount = 2;
                    char fname[2048 + 1];
                    char response[2048 + 1];
                    char *finalkey = NULL;
                    response[2048] = '\0';
                    fname[2048] = '\0';
                    if (!OS_IsValidName(agentname)) {
                        merror("%s: ERROR: Invalid agent name: %s from %s", ARGV0, agentname, srcip);
                        snprintf(response, 2048, "ERROR: Invalid agent name: %s\n\n", agentname);
                        SSL_write(ssl, response, strlen(response));
                        snprintf(response, 2048, "ERROR: Unable to add agent.\n\n");
                        SSL_write(ssl, response, strlen(response));
                        sleep(1);
                        exit(0);
                    }

                    /* Check for duplicated names */
                    strncpy(fname, agentname, 2048);
                    while (NameExist(fname)) {
                        snprintf(fname, 2048, "%s%d", agentname, acount);
                        acount++;
                        if (acount > 256) {
                            merror("%s: ERROR: Invalid agent name %s (duplicated)", ARGV0, agentname);
                            snprintf(response, 2048, "ERROR: Invalid agent name: %s\n\n", agentname);
                            SSL_write(ssl, response, strlen(response));
                            snprintf(response, 2048, "ERROR: Unable to add agent.\n\n");
                            SSL_write(ssl, response, strlen(response));
                            sleep(1);
                            exit(0);
                        }
                    }
                    agentname = fname;

                    /* Check for duplicated IP */

                    if (use_ip_address) {
                        id_exist = IPExist(srcip);
                        if (id_exist) {
                            if (force_antiquity >= 0) {
                                double antiquity = OS_AgentAntiquity(id_exist);
                                if (antiquity >= force_antiquity || antiquity < 0) {
                                    /* TODO: Backup info-agent, syscheck and rootcheck */
                                    OS_RemoveAgent(id_exist);
                                } else {
                                    /* TODO: Send alert */
                                    merror("%s: ERROR: Duplicated IP %s (another active)", ARGV0, srcip);
                                    snprintf(response, 2048, "ERROR: Duplicated IP: %s\n\n", srcip);
                                    SSL_write(ssl, response, strlen(response));
                                    snprintf(response, 2048, "ERROR: Unable to add agent.\n\n");
                                    SSL_write(ssl, response, strlen(response));
                                    sleep(1);
                                    exit(0);
                                }

                            } else {
                                merror("%s: ERROR: Duplicated IP %s", ARGV0, srcip);
                                snprintf(response, 2048, "ERROR: Duplicated IP: %s\n\n", srcip);
                                SSL_write(ssl, response, strlen(response));
                                snprintf(response, 2048, "ERROR: Unable to add agent.\n\n");
                                SSL_write(ssl, response, strlen(response));
                                sleep(1);
                                exit(0);
                            }
                        }
                    }

                    /* Add the new agent */
                    if (use_ip_address)
                        finalkey = OS_AddNewAgent(agentname, srcip, NULL);
                    else
                        finalkey = OS_AddNewAgent(agentname, NULL, NULL);

                    if (!finalkey) {
                        merror("%s: ERROR: Unable to add agent: %s (internal error)", ARGV0, agentname);
                        snprintf(response, 2048, "ERROR: Internal manager error adding agent: %s\n\n", agentname);
                        SSL_write(ssl, response, strlen(response));
                        snprintf(response, 2048, "ERROR: Unable to add agent.\n\n");
                        SSL_write(ssl, response, strlen(response));
                        sleep(1);
                        exit(0);
                    }

                    snprintf(response, 2048, "OSSEC K:'%s'\n\n", finalkey);
                    verbose("%s: INFO: Agent key generated for %s (requested by %s)", ARGV0, agentname, srcip);
                    ret = SSL_write(ssl, response, strlen(response));
                    if (ret < 0) {
                        merror("%s: ERROR: SSL write error (%d)", ARGV0, ret);
                        merror("%s: ERROR: Agen key not saved for %s", ARGV0, agentname);
                        ERR_print_errors_fp(stderr);
                    } else {
                        verbose("%s: INFO: Agent key created for %s (requested by %s)", ARGV0, agentname, srcip);
                    }
                }

                clean_exit(ctx, client_sock);
            }
        }
    }

    /* Shut down the socket */
    clean_exit(ctx, sock);

    return (0);
}