Example #1
0
jsonObject* oilsUtilsFetchWorkstationByName( const char* name ) {
	jsonObject* p = jsonParseFmt("{\"name\":\"%s\"}", name);
	jsonObject* r = oilsUtilsCStoreReq(
		"open-ils.cstore.direct.actor.workstation.search", p);
	jsonObjectFree(p);
	return r;
}
Example #2
0
// free() response
static char* oilsAuthGetSalt(int user_id) {
    char* salt_str = NULL;

    jsonObject* params = jsonParseFmt( // free
        "{\"from\":[\"actor.get_salt\",%d,\"%s\"]}", user_id, "main");

    jsonObject* salt_obj = // free
        oilsUtilsCStoreReq("open-ils.cstore.json_query", params);

    jsonObjectFree(params);

    if (salt_obj) {

        if (salt_obj->type != JSON_NULL) {

            const char* salt_val = jsonObjectGetString(
                jsonObjectGetKeyConst(salt_obj, "actor.get_salt"));

            // caller expects a free-able string, could be NULL.
            if (salt_val) { salt_str = strdup(salt_val); } 
        }

        jsonObjectFree(salt_obj);
    }

    return salt_str;
}
Example #3
0
/**
	@brief Verify the password received from the client.
	@param ctx The method context.
	@param userObj An object from the database, representing the user.
	@param password An obfuscated password received from the client.
	@return 1 if the password is valid; 0 if it isn't; or -1 upon error.

	(None of the so-called "passwords" used here are in plaintext.  All have been passed
	through at least one layer of hashing to obfuscate them.)

	Take the password from the user object.  Append it to the username seed from memcache,
	as stored previously by a call to the init method.  Take an md5 hash of the result.
	Then compare this hash to the password received from the client.

	In order for the two to match, other than by dumb luck, the client had to construct
	the password it passed in the same way.  That means it neded to know not only the
	original password (either hashed or plaintext), but also the seed.  The latter requirement
	means that the client process needs either to be the same process that called the init
	method or to receive the seed from the process that did so.
*/
static int oilsAuthVerifyPassword( const osrfMethodContext* ctx, int user_id, 
        const char* identifier, const char* password, const char* nonce) {

    int verified = 0;

    // We won't be needing the seed again, remove it
    osrfCacheRemove("%s%s%s", OILS_AUTH_CACHE_PRFX, identifier, nonce);

    // Ask the DB to verify the user's password.
    // Here, the password is md5(md5(password) + salt)

    jsonObject* params = jsonParseFmt( // free
        "{\"from\":[\"actor.verify_passwd\",%d,\"main\",\"%s\"]}", 
        user_id, password);

    jsonObject* verify_obj = // free 
        oilsUtilsCStoreReq("open-ils.cstore.json_query", params);

    jsonObjectFree(params);

    if (verify_obj) {
        verified = oilsUtilsIsDBTrue(
            jsonObjectGetString(
                jsonObjectGetKeyConst(
                    verify_obj, "actor.verify_passwd")));

        jsonObjectFree(verify_obj);
    }

    char* countkey = va_list_to_string("%s%s%s", 
        OILS_AUTH_CACHE_PRFX, identifier, OILS_AUTH_COUNT_SFFX );
    jsonObject* countobject = osrfCacheGetObject( countkey );
    if(countobject) {
        long failcount = (long) jsonObjectGetNumber( countobject );
        if(failcount >= _oilsAuthBlockCount) {
            verified = 0;
            osrfLogInfo(OSRF_LOG_MARK, 
                "oilsAuth found too many recent failures for '%s' : %i, "
                "forcing failure state.", identifier, failcount);
        }
        if(verified == 0) {
            failcount += 1;
        }
        jsonObjectSetNumber( countobject, failcount );
        osrfCachePutObject( countkey, countobject, _oilsAuthBlockTimeout );
        jsonObjectFree(countobject);
    }
    free(countkey);

    return verified;
}
Example #4
0
/**
 * Returns true if the provided password is correct.
 * Turn the password into the nested md5 hash required of migrated
 * passwords, then check the password in the DB.
 */
static int oilsAuthLoginCheckPassword(int user_id, const char* password) {

    growing_buffer* gb = buffer_init(33); // free me 1
    char* salt = oilsAuthGetSalt(user_id); // free me 2
    char* passhash = md5sum(password); // free me 3

    buffer_add(gb, salt); // gb strdup's internally
    buffer_add(gb, passhash);

    free(salt); // free 2
    free(passhash); // free 3

    // salt + md5(password)
    passhash = buffer_release(gb); // free 1 ; free me 4
    char* finalpass = md5sum(passhash); // free me 5

    free(passhash); // free 4

    jsonObject *arr = jsonNewObjectType(JSON_ARRAY);
    jsonObjectPush(arr, jsonNewObject("actor.verify_passwd"));
    jsonObjectPush(arr, jsonNewNumberObject((long) user_id));
    jsonObjectPush(arr, jsonNewObject("main"));
    jsonObjectPush(arr, jsonNewObject(finalpass));
    jsonObject *params = jsonNewObjectType(JSON_HASH); // free me 6
    jsonObjectSetKey(params, "from", arr);

    free(finalpass); // free 5

    jsonObject* verify_obj = // free 
        oilsUtilsCStoreReq("open-ils.cstore.json_query", params);

    jsonObjectFree(params); // free 6

    if (!verify_obj) return 0; // error

    int verified = oilsUtilsIsDBTrue(
        jsonObjectGetString(
            jsonObjectGetKeyConst(verify_obj, "actor.verify_passwd")
        )
    );

    jsonObjectFree(verify_obj);

    return verified;
}
Example #5
0
oilsEvent* oilsUtilsCheckPerms( int userid, int orgid, char* permissions[], int size ) {
    if (!permissions) return NULL;
    int i;

    // Check perms against the root org unit if no org unit is provided.
    if (orgid == -1)
        orgid = oilsUtilsGetRootOrgId();

    for( i = 0; i < size && permissions[i]; i++ ) {
        oilsEvent* evt = NULL;
        char* perm = permissions[i];

        jsonObject* params = jsonParseFmt(
            "{\"from\":[\"permission.usr_has_perm\",\"%d\",\"%s\",\"%d\"]}",
            userid, perm, orgid
        );

        // Execute the query
        jsonObject* result = oilsUtilsCStoreReq(
            "open-ils.cstore.json_query", params);

        const jsonObject* hasPermStr = 
            jsonObjectGetKeyConst(result, "permission.usr_has_perm");

        if (!oilsUtilsIsDBTrue(jsonObjectGetString(hasPermStr))) {
            evt = oilsNewEvent3(
                OSRF_LOG_MARK, OILS_EVENT_PERM_FAILURE, perm, orgid);
        }

        jsonObjectFree(params);
        jsonObjectFree(result);

        // return first failed permission check.
        if (evt) return evt;
    }

    return NULL; // all perm checks succeeded
}
Example #6
0
/**
	@brief Convert a string to a number representing a time interval in seconds.
	@param interval Pointer to string, e.g. "420" or "2 weeks".
	@return If successful, the number of seconds that the string represents; otherwise -1.

	If the string is all digits (apart from any leading or trailing white space), convert
	it directly.  Otherwise pass it to PostgreSQL for translation.

	The result is the same as if we were to pass every string to PostgreSQL, except that,
	depending on the value of LONG_MAX, we return values for some strings that represent
	intervals too long for PostgreSQL to represent (i.e. more than 2147483647 seconds).

	WARNING: a valid interval of -1 second will be indistinguishable from an error.  If
	such an interval is a plausible possibility, don't use this function.
*/
long oilsUtilsIntervalToSeconds( const char* s ) {

	if( !s ) {
		osrfLogWarning( OSRF_LOG_MARK, "String to be converted is NULL" );
		return -1;
	}

	// Skip leading white space
	while( isspace( (unsigned char) *s ))
		++s;

	if( '\0' == *s ) {
		osrfLogWarning( OSRF_LOG_MARK, "String to be converted is empty or all white space" );
		return -1;
	}

	// See if the string is a raw number, i.e. all digits
	// (apart from any leading or trailing white space)

	const char* p = s;   // For traversing and examining the remaining string
	if( isdigit( (unsigned char) *p )) {
		// Looks like a number so far...skip over the digits
		do {
			++p;
		} while( isdigit( (unsigned char) *p ));
		// Skip over any following white space
		while( isspace( (unsigned char) *p ))
			++p;
		if( '\0' == *p ) {
			// This string is a raw number.  Convert it directly.
			long n = strtol( s, NULL, 10 );
			if( LONG_MAX == n ) {
				// numeric overflow
				osrfLogWarning( OSRF_LOG_MARK,
					"String \"%s\"represents a number too big for a long", s );
				return -1;
			} else
				return n;
		}
	}

	// If we get to this point, the string is not all digits.  Pass it to PostgreSQL.

	// Build the query
	jsonObject* query_obj = jsonParseFmt(
		"{\"from\":[\"config.interval_to_seconds\",\"%s\"]}", s );

	// Execute the query
	jsonObject* result = oilsUtilsCStoreReq(
		"open-ils.cstore.json_query", query_obj );
	jsonObjectFree( query_obj );

	// Get the results
	const jsonObject* seconds_obj = jsonObjectGetKeyConst( result, "config.interval_to_seconds" );
	long seconds = -1;
	if( seconds_obj && JSON_NUMBER == seconds_obj->type )
		seconds = (long) jsonObjectGetNumber( seconds_obj );
	else
		osrfLogError( OSRF_LOG_MARK,
			"Error calling json_query to convert \"%s\" to seconds", s );

	jsonObjectFree( result );
	return seconds;
}