static bool _mongoc_server_session_uuid (uint8_t *data /* OUT */, bson_error_t *error) { #ifdef MONGOC_ENABLE_CRYPTO /* https://tools.ietf.org/html/rfc4122#page-14 * o Set the two most significant bits (bits 6 and 7) of the * clock_seq_hi_and_reserved to zero and one, respectively. * * o Set the four most significant bits (bits 12 through 15) of the * time_hi_and_version field to the 4-bit version number from * Section 4.1.3. * * o Set all the other bits to randomly (or pseudo-randomly) chosen * values. */ if (!_mongoc_rand_bytes (data, 16)) { bson_set_error (error, MONGOC_ERROR_CLIENT, MONGOC_ERROR_CLIENT_SESSION_FAILURE, "Could not generate UUID for logical session id"); return false; } data[6] = (uint8_t) (0x40 | (data[6] & 0xf)); data[8] = (uint8_t) (0x80 | (data[8] & 0x3f)); return true; #else /* no _mongoc_rand_bytes without a crypto library */ bson_set_error (error, MONGOC_ERROR_CLIENT, MONGOC_ERROR_CLIENT_SESSION_FAILURE, "Could not generate UUID for logical session id, we need a" " cryptography library like libcrypto, Common Crypto, or" " CNG"); return false; #endif }
/* generate client-first-message: * n,a=authzid,n=encoded-username,r=client-nonce * * note that a= is optional, so we aren't dealing with that here */ static bool _mongoc_scram_start (mongoc_scram_t *scram, uint8_t *outbuf, uint32_t outbufmax, uint32_t *outbuflen, bson_error_t *error) { uint8_t nonce[24]; const char *ptr; bool rval = true; BSON_ASSERT (scram); BSON_ASSERT (outbuf); BSON_ASSERT (outbufmax); BSON_ASSERT (outbuflen); if (!scram->user) { bson_set_error (error, MONGOC_ERROR_SCRAM, MONGOC_ERROR_SCRAM_PROTOCOL_ERROR, "SCRAM Failure: username is not set"); goto FAIL; } /* auth message is as big as the outbuf just because */ scram->auth_message = (uint8_t *) bson_malloc (outbufmax); scram->auth_messagemax = outbufmax; /* the server uses a 24 byte random nonce. so we do as well */ if (1 != _mongoc_rand_bytes (nonce, sizeof (nonce))) { bson_set_error (error, MONGOC_ERROR_SCRAM, MONGOC_ERROR_SCRAM_PROTOCOL_ERROR, "SCRAM Failure: could not generate a cryptographically " "secure nonce in sasl step 1"); goto FAIL; } scram->encoded_nonce_len = bson_b64_ntop (nonce, sizeof (nonce), scram->encoded_nonce, sizeof (scram->encoded_nonce)); if (-1 == scram->encoded_nonce_len) { bson_set_error (error, MONGOC_ERROR_SCRAM, MONGOC_ERROR_SCRAM_PROTOCOL_ERROR, "SCRAM Failure: could not encode nonce"); goto FAIL; } if (!_mongoc_scram_buf_write ("n,,n=", -1, outbuf, outbufmax, outbuflen)) { goto BUFFER; } for (ptr = scram->user; *ptr; ptr++) { /* RFC 5802 specifies that ',' and '=' and encoded as '=2C' and '=3D' * respectively in the user name */ switch (*ptr) { case ',': if (!_mongoc_scram_buf_write ( "=2C", -1, outbuf, outbufmax, outbuflen)) { goto BUFFER; } break; case '=': if (!_mongoc_scram_buf_write ( "=3D", -1, outbuf, outbufmax, outbuflen)) { goto BUFFER; } break; default: if (!_mongoc_scram_buf_write (ptr, 1, outbuf, outbufmax, outbuflen)) { goto BUFFER; } break; } } if (!_mongoc_scram_buf_write (",r=", -1, outbuf, outbufmax, outbuflen)) { goto BUFFER; } if (!_mongoc_scram_buf_write (scram->encoded_nonce, scram->encoded_nonce_len, outbuf, outbufmax, outbuflen)) { goto BUFFER; } /* we have to keep track of the conversation to create a client proof later * on. This copies the message we're crafting from the 'n=' portion onwards * into a buffer we're managing */ if (!_mongoc_scram_buf_write ((char *) outbuf + 3, *outbuflen - 3, scram->auth_message, scram->auth_messagemax, &scram->auth_messagelen)) { goto BUFFER_AUTH; } if (!_mongoc_scram_buf_write (",", -1, scram->auth_message, scram->auth_messagemax, &scram->auth_messagelen)) { goto BUFFER_AUTH; } goto CLEANUP; BUFFER_AUTH: bson_set_error ( error, MONGOC_ERROR_SCRAM, MONGOC_ERROR_SCRAM_PROTOCOL_ERROR, "SCRAM Failure: could not buffer auth message in sasl step1"); goto FAIL; BUFFER: bson_set_error (error, MONGOC_ERROR_SCRAM, MONGOC_ERROR_SCRAM_PROTOCOL_ERROR, "SCRAM Failure: could not buffer sasl step1"); goto FAIL; FAIL: rval = false; CLEANUP: return rval; }