Example #1
0
// make a random 32-char string
// (the MD5 of some quasi-random bits)
//
int make_random_string(char* out) {
    char buf[256];
#ifdef _WIN32
    HCRYPTPROV hCryptProv;
        
    if(! CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0)) {
        return -1;
    }
    
    if(! CryptGenRandom(hCryptProv, (DWORD) 32, (BYTE *) buf)) {
        CryptReleaseContext(hCryptProv, 0);
        return -1;
    }
        
    CryptReleaseContext(hCryptProv, 0);
#elif defined ANDROID
    // /dev/random not available on Android, using stdlib function instead
    int i = rand();
    snprintf(buf, sizeof(buf), "%d", i);
#else
#ifndef _USING_FCGI_
    FILE* f = fopen("/dev/random", "r");
#else
    FILE* f = FCGI::fopen("/dev/random", "r");
#endif
    if (!f) {
        return -1;
    }
    size_t n = fread(buf, 32, 1, f);
    fclose(f);
    if (n != 1) return -1;
#endif
    md5_block((const unsigned char*)buf, 32, out);
    return 0;
}
Example #2
0
// update the DB record to the values in "xhost"
// "initial_host" stores the current DB values;
// update only those fields that have changed
//
static int update_host_record(HOST& initial_host, HOST& xhost, USER& user) {
    DB_HOST host;
    int retval;
    char buf[1024];

    host = xhost;

    // hash the CPID reported by the host with the user's email address.
    // This prevents one user from spoofing another one's host.
    //
    if (strlen(host.host_cpid)) {
        sprintf(buf, "%s%s", host.host_cpid, user.email_addr);
        md5_block((const unsigned char*)buf, strlen(buf), host.host_cpid);
    }

    char* p = getenv("REMOTE_ADDR");
    if (p) {
        strlcpy(host.external_ip_addr, p, sizeof(host.external_ip_addr));
    }
    retval = host.update_diff_sched(initial_host);
    if (retval) {
        log_messages.printf(MSG_CRITICAL,
                            "host.update() failed: %s\n", boincerror(retval)
                           );
    }
    return 0;
}
Example #3
0
int make_random_string(char* out) {
    char buf[256];
#ifdef _WIN32
    HCRYPTPROV hCryptProv;
        
    if(! CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0)) {
        return -1;
    }
    
    if(! CryptGenRandom(hCryptProv, (DWORD) 32, (BYTE *) buf)) {
        CryptReleaseContext(hCryptProv, 0);
        return -1;
    }
        
    CryptReleaseContext(hCryptProv, 0);
#else
    FILE* f = fopen("/dev/random", "r");
    if (!f) {
        return -1;
    }
    size_t n = fread(buf, 32, 1, f);
    fclose(f);
    if (n != 1) return -1;
#endif
    md5_block((const unsigned char*)buf, 32, out);
    return 0;
}
Example #4
0
void MD5_Update(MD5_CTX *c, register unsigned char *data, MD5_LONG len)
{
	register ULONG *p;
	int sw,sc;
	ULONG l;

	if (len == 0) return;

	l=(c->Nl+(len<<3))&0xffffffffL;
	/* 95-05-24 eay Fixed a bug with the overflow handling, thanks to
	 * Wei Dai <*****@*****.**> for pointing it out. */
	if (l < c->Nl) /* overflow */
		c->Nh++;
	c->Nh+=(len>>29);
	c->Nl=l;

	if (c->num != 0) {
		p=c->data;
		sw=c->num>>2;
		sc=c->num&0x03;

		if ((c->num+len) >= MD5_CBLOCK) {
			l= p[sw];
			p_c2l(data,l,sc);
			p[sw++]=l;
			for (; sw<MD5_LBLOCK; sw++) {
				c2l(data,l);
				p[sw]=l;
			}
			len-=(MD5_CBLOCK-c->num);

			md5_block(c,p);
			c->num=0;
			/* drop through and do the rest */
		} else {
			int ew,ec;

			c->num+=(int)len;
			if ((sc+len) < 4) { /* ugly, add char's to a word */
				l= p[sw];
				p_c2l_p(data,l,sc,len);
				p[sw]=l;
			} else {
				ew=(c->num>>2);
				ec=(c->num&0x03);
				l= p[sw];
				p_c2l(data,l,sc);
				p[sw++]=l;
				for (; sw < ew; sw++)
					{ c2l(data,l); p[sw]=l; }
				if (ec) {
					c2l_p(data,l,ec);
					p[sw]=l;
				}
			}
			return;
		}
	}
Example #5
0
// find the user's most recently-created host with given host CPID
//
static bool find_host_by_cpid(DB_USER& user, char* host_cpid, DB_HOST& host) {
    char buf[1024], buf2[256];
    sprintf(buf, "%s%s", host_cpid, user.email_addr);
    md5_block((const unsigned char*)buf, strlen(buf), buf2);

    sprintf(buf,
            "where userid=%d and host_cpid='%s' order by id desc", user.id, buf2
           );
    if (!host.enumerate(buf)) {
        host.end_enumerate();
        return true;
    }
    return false;
}
Example #6
0
int sign_block(DATA_BLOCK& data_block, R_RSA_PRIVATE_KEY& key, DATA_BLOCK& signature) {
    char md5_buf[MD5_LEN];
    int retval;
    DATA_BLOCK in_block;

    md5_block(data_block.data, data_block.len, md5_buf);
    in_block.data = (unsigned char*)md5_buf;
    in_block.len = (unsigned int)strlen(md5_buf);
    retval = encrypt_private(key, in_block, signature);
    if (retval) {
        printf("sign_block: encrypt_private returned %d\n", retval);
        return retval;
    }
    return 0;
}
// make a host cross-project ID.
// Should be unique across hosts with very high probability
//
void HOST_INFO::generate_host_cpid() {
// Assume that get_mac_addresses can be ported to any unix system.
// If not, it can return false.
//
#if defined(__linux__) || defined(_WIN32) || defined(__APPLE__ ) || defined(__unix)
    char buffer[8192] = "";
        // must be big enough to accommodate aa:bb:cc:dd:ee:ff
        // times the number of network interfaces,
        // plus the domain name, IP addr, and OS name.
        // 8K should suffice

    if (!get_mac_addresses(buffer) || ! strcmp(buffer, "")) {
        make_random_string("", host_cpid);
        return;
    }
    strcat(buffer, domain_name);
    strcat(buffer, ip_addr);
    strcat(buffer, os_name);
    md5_block((unsigned char*)buffer, (int)strlen(buffer), host_cpid);
#else
    make_random_string("", host_cpid);
#endif
}
Example #8
0
// same, both text and signature are char strings
//
int check_string_signature(
    const char* text, const char* signature_text, R_RSA_PUBLIC_KEY& key,
    bool& answer
) {
    char md5_buf[MD5_LEN];
    unsigned char signature_buf[SIGNATURE_SIZE_BINARY];
    char clear_buf[MD5_LEN];
    int retval, n;
    DATA_BLOCK signature, clear_signature;

    retval = md5_block((const unsigned char*)text, (int)strlen(text), md5_buf);
    if (retval) return retval;
    n = (int)strlen(md5_buf);
    signature.data = signature_buf;
    signature.len = sizeof(signature_buf);
    retval = sscan_hex_data(signature_text, signature);
    if (retval) return retval;
    clear_signature.data = (unsigned char*)clear_buf;
    clear_signature.len = 256;
    retval = decrypt_public(key, signature, clear_signature);
    if (retval) return retval;
    answer = !strncmp(md5_buf, clear_buf, n);
    return 0;
}
// make a random string using host info.
// Not recommended for password generation;
// use as a last resort if more secure methods fail
//
void HOST_INFO::make_random_string(const char* salt, char* out) {
    char buf[1024];

    sprintf(buf, "%f%s%s%f%s", dtime(), domain_name, ip_addr, d_free, salt);
    md5_block((const unsigned char*) buf, (int)strlen(buf), out);
}
Example #10
0
void MD5_Update(MD5_CTX *c, register unsigned char *data, unsigned long len)
{
	register ULONG *p;
	int sw,sc;
	ULONG l;

	if (len == 0) return;

	l=(c->Nl+(len<<3))&0xffffffffL;
	if (l < c->Nl) /* overflow */
		c->Nh++;
	c->Nh+=(len>>29);
	c->Nl=l;

	if (c->num != 0)
		{
		p=c->data;
		sw=c->num>>2;
		sc=c->num&0x03;

		if ((c->num+len) >= MD5_CBLOCK)
			{
			l= p[sw];
			p_c2l(data,l,sc);
			p[sw++]=l;
			for (; sw<MD5_LBLOCK; sw++)
				{
				c2l(data,l);
				p[sw]=l;
				}
			len-=(MD5_CBLOCK-c->num);

			md5_block(c,p);
			c->num=0;
			/* drop through and do the rest */
			}
		else
			{
			int ew,ec;

			c->num+=(int)len;
			if ((sc+len) < 4) /* ugly, add char's to a word */
				{
				l= p[sw];
				p_c2l_p(data,l,sc,len);
				p[sw]=l;
				}
			else
				{
				ew=(c->num>>2);
				ec=(c->num&0x03);
				l= p[sw];
				p_c2l(data,l,sc);
				p[sw++]=l;
				for (; sw < ew; sw++)
					{ c2l(data,l); p[sw]=l; }
				if (ec)
					{
					c2l_p(data,l,ec);
					p[sw]=l;
					}
				}
			return;
			}
		}
Example #11
0
void get_rss_auth(USER& user, char* buf) {
    char buf2[256], out[256];
    sprintf(buf2, "%s%s%s", user.authenticator, user.passwd_hash, "notify_rss");
    md5_block((unsigned char*)buf2, strlen(buf2), out);
    sprintf(buf, "%d_%s", user.id, out);
}
Example #12
0
// Based on the info in the request message,
// look up the host and its user, and make sure the authenticator matches.
// Some special cases:
//  1) If no host ID is supplied, or if RPC seqno mismatch,
//     create a new host record
//  2) If the host record specified by g_request->hostid is a "zombie"
//     (i.e. it was merged with another host via the web site)
//     then follow links to find the proper host
//
// POSTCONDITION:
// If this function returns zero, then:
// - reply.host contains a valid host record (possibly new)
// - reply.user contains a valid user record
// - if user belongs to a team, reply.team contains team record
//
int authenticate_user() {
    int retval;
    char buf[1024];
    DB_HOST host;
    DB_USER user;
    DB_TEAM team;

    if (g_request->hostid) {
        retval = host.lookup_id(g_request->hostid);
        while (!retval && host.userid==0) {
            // if host record is zombie, follow link to new host
            //
            retval = host.lookup_id(host.rpc_seqno);
            if (!retval) {
                g_reply->hostid = host.id;
                log_messages.printf(MSG_NORMAL,
                                    "[HOST#%d] forwarding to new host ID %d\n",
                                    g_request->hostid, host.id
                                   );
            }
        }
        if (retval) {
            g_reply->insert_message("Can't find host record", "low");
            log_messages.printf(MSG_NORMAL,
                                "[HOST#%d?] can't find host\n",
                                g_request->hostid
                               );
            g_request->hostid = 0;
            goto lookup_user_and_make_new_host;
        }

        g_reply->host = host;

        // look up user based on the ID in host record,
        // and see if the authenticator matches (regular or weak)
        //
        g_request->using_weak_auth = false;
        sprintf(buf, "where id=%d", host.userid);
        retval = user.lookup(buf);
        if (!retval && !strcmp(user.authenticator, g_request->authenticator)) {
            // req auth matches user auth - go on
        } else {
            if (!retval) {
                // user for host.userid exists - check weak auth
                //
                get_weak_auth(user, buf);
                if (!strcmp(buf, g_request->authenticator)) {
                    g_request->using_weak_auth = true;
                    log_messages.printf(MSG_DEBUG,
                                        "[HOST#%d] accepting weak authenticator\n",
                                        host.id
                                       );
                }
            }
            if (!g_request->using_weak_auth) {
                // weak auth failed - look up user based on authenticator
                //
                strlcpy(
                    user.authenticator, g_request->authenticator, sizeof(user.authenticator)
                );
                escape_string(user.authenticator, sizeof(user.authenticator));
                sprintf(buf, "where authenticator='%s'", user.authenticator);
                retval = user.lookup(buf);
                if (retval) {
                    g_reply->insert_message(
                        _("Invalid or missing account key.  To fix, remove and add this project."),
                        "notice"
                    );
                    g_reply->set_delay(DELAY_MISSING_KEY);
                    g_reply->nucleus_only = true;
                    log_messages.printf(MSG_CRITICAL,
                                        "[HOST#%d] [USER#%d] Bad authenticator '%s'\n",
                                        host.id, user.id, g_request->authenticator
                                       );
                    return ERR_AUTHENTICATOR;
                }
            }
        }

        g_reply->user = user;

        if (host.userid != user.id) {
            // If the request's host ID isn't consistent with the authenticator,
            // create a new host record.
            //
            log_messages.printf(MSG_NORMAL,
                                "[HOST#%d] [USER#%d] inconsistent host ID; creating new host\n",
                                host.id, user.id
                               );
            goto make_new_host;
        }


        // If the seqno from the host is less than what we expect,
        // the user must have copied the state file to a different host.
        // Make a new host record.
        //
        if (!batch && g_request->rpc_seqno < g_reply->host.rpc_seqno) {
            g_request->hostid = 0;
            log_messages.printf(MSG_NORMAL,
                                "[HOST#%d] [USER#%d] RPC seqno %d less than expected %d; creating new host\n",
                                g_reply->host.id, user.id, g_request->rpc_seqno, g_reply->host.rpc_seqno
                               );
            goto make_new_host;
        }

    } else {
        // Here no hostid was given, or the ID was bad.
        // Look up the user, then create a new host record
        //
lookup_user_and_make_new_host:
        // if authenticator contains _, it's a weak auth
        //
        if (strchr(g_request->authenticator, '_')) {
            int userid = atoi(g_request->authenticator);
            retval = user.lookup_id(userid);
            if (!retval) {
                get_weak_auth(user, buf);
                if (strcmp(buf, g_request->authenticator)) {
                    retval = ERR_AUTHENTICATOR;
                }
            }
        } else {
            strlcpy(
                user.authenticator, g_request->authenticator,
                sizeof(user.authenticator)
            );
            escape_string(user.authenticator, sizeof(user.authenticator));
            sprintf(buf, "where authenticator='%s'", user.authenticator);
            retval = user.lookup(buf);
        }
        if (retval) {
            g_reply->insert_message(
                "Invalid or missing account key.  To fix, remove and add this project .",
                "low"
            );
            g_reply->set_delay(DELAY_MISSING_KEY);
            log_messages.printf(MSG_CRITICAL,
                                "[HOST#<none>] Bad authenticator '%s': %s\n",
                                g_request->authenticator, boincerror(retval)
                               );
            return ERR_AUTHENTICATOR;
        }
        g_reply->user = user;

        // If host CPID is present,
        // scan backwards through this user's hosts,
        // looking for one with the same host CPID.
        // If we find one, it means the user detached and reattached.
        // Use the existing host record,
        // and mark in-progress results as over.
        //
        if (strlen(g_request->host.host_cpid)) {
            if (find_host_by_cpid(user, g_request->host.host_cpid, host)) {
                log_messages.printf(MSG_NORMAL,
                                    "[HOST#%d] [USER#%d] No host ID in request, but host with matching CPID found.\n",
                                    host.id, host.userid
                                   );
                if ((g_request->allow_multiple_clients != 1)
                        && (g_request->other_results.size() == 0)
                   ) {
                    mark_results_over(host);
                }
                goto got_host;
            }
        }

make_new_host:
        // One final attempt to locate an existing host record:
        // scan backwards through this user's hosts,
        // looking for one with the same host name,
        // IP address, processor and amount of RAM.
        // If found, use the existing host record,
        // and mark in-progress results as over.
        //
        // NOTE: If the client was run with --allow_multiple_clients, skip this.
        //
        if ((g_request->allow_multiple_clients != 1)
                && find_host_by_other(user, g_request->host, host)
           ) {
            log_messages.printf(MSG_NORMAL,
                                "[HOST#%d] [USER#%d] Found similar existing host for this user - assigned.\n",
                                host.id, host.userid
                               );
            mark_results_over(host);
            goto got_host;
        }
        // either of the above cases,
        // or host ID didn't match user ID,
        // or RPC seqno was too low.
        //
        // Create a new host.
        // g_reply->user is filled in and valid at this point
        //
        host = g_request->host;
        host.id = 0;
        host.create_time = time(0);
        host.userid = g_reply->user.id;
        host.rpc_seqno = 0;
        host.expavg_time = time(0);
        safe_strcpy(host.venue, g_reply->user.venue);
        host.fix_nans();
        retval = host.insert();
        if (retval) {
            g_reply->insert_message(
                "Couldn't create host record in database", "low"
            );
            boinc_db.print_error("host.insert()");
            log_messages.printf(MSG_CRITICAL, "host.insert() failed\n");
            return retval;
        }
        host.id = boinc_db.insert_id();

got_host:
        g_reply->host = host;
        g_reply->hostid = g_reply->host.id;
        // this tells client to updates its host ID
        g_request->rpc_seqno = 0;
        // this value eventually gets written to host DB record;
        // for new hosts it must be zero.
        // This kludge forces this.
    }

    // have user record in g_reply->user at this point
    //

    if (g_reply->user.teamid) {
        retval = team.lookup_id(g_reply->user.teamid);
        if (!retval) g_reply->team = team;
    }

    // compute email hash
    //
    md5_block(
        (unsigned char*)g_reply->user.email_addr,
        strlen(g_reply->user.email_addr),
        g_reply->email_hash
    );

    // if new user CPID, update user record
    //
    if (!g_request->using_weak_auth && strlen(g_request->cross_project_id)) {
        if (strcmp(g_request->cross_project_id, g_reply->user.cross_project_id)) {
            user.id = g_reply->user.id;
            escape_string(g_request->cross_project_id, sizeof(g_request->cross_project_id));
            sprintf(buf, "cross_project_id='%s'", g_request->cross_project_id);
            unescape_string(g_request->cross_project_id, sizeof(g_request->cross_project_id));
            user.update_field(buf);
        }
    }

    return 0;
}
Example #13
0
std::string md5_string(const unsigned char* data, int nbytes) {
    char output[MD5_LEN];
    md5_block(data, nbytes, output);
    return std::string(output);
}