Esempio n. 1
0
static ha_node_t *
ha_node_new (const char       *name,
             const char       *repl_set,
             const char       *dbpath,
             bson_bool_t       is_arbiter,
             bson_bool_t       is_config,
             bson_bool_t       is_router,
             bson_uint16_t     port)
{
   ha_node_t *node;

   node = bson_malloc0(sizeof *node);
   node->name = bson_strdup(name);
   node->repl_set = bson_strdup(repl_set);
   node->dbpath = bson_strdup(dbpath);
   node->is_arbiter = is_arbiter;
   node->is_config = is_config;
   node->is_router = is_router;
   node->port = port;

   return node;
}
void
mongoc_write_concern_set_wtag (mongoc_write_concern_t *write_concern,
                               const char             *wtag)
{
   BSON_ASSERT (write_concern);

   if (!_mongoc_write_concern_warn_frozen (write_concern)) {
      bson_free (write_concern->wtag);
      write_concern->wtag = bson_strdup (wtag);
      write_concern->w = MONGOC_WRITE_CONCERN_W_TAG;
      write_concern->is_default = false;
   }
}
mongoc_bulk_operation_t *
_mongoc_bulk_operation_new (mongoc_client_t              *client,        /* IN */
                            const char                   *database,      /* IN */
                            const char                   *collection,    /* IN */
                            mongoc_bulk_write_flags_t     flags,         /* IN */
                            const mongoc_write_concern_t *write_concern) /* IN */
{
   mongoc_bulk_operation_t *bulk;

   BSON_ASSERT (client);
   BSON_ASSERT (collection);

   bulk = mongoc_bulk_operation_new (flags.ordered);
   bulk->client = client;
   bulk->database = bson_strdup (database);
   bulk->collection = bson_strdup (collection);
   bulk->write_concern = mongoc_write_concern_copy (write_concern);
   bulk->executed = false;
   bulk->flags = flags;
   bulk->operation_id = ++client->cluster.operation_id;

   return bulk;
}
mongoc_bulk_operation_t *
_mongoc_bulk_operation_new (mongoc_client_t              *client,        /* IN */
                            const char                   *database,      /* IN */
                            const char                   *collection,    /* IN */
                            uint32_t                      hint,          /* IN */
                            bool                          ordered,       /* IN */
                            const mongoc_write_concern_t *write_concern) /* IN */
{
   mongoc_bulk_operation_t *bulk;

   BSON_ASSERT (client);
   BSON_ASSERT (collection);

   bulk = mongoc_bulk_operation_new (ordered);
   bulk->client = client;
   bulk->database = bson_strdup (database);
   bulk->collection = bson_strdup (collection);
   bulk->hint = hint;
   bulk->write_concern = mongoc_write_concern_copy (write_concern);
   bulk->executed = false;

   return bulk;
}
Esempio n. 5
0
/**
 * mongoc_read_concern_set_level:
 * @read_concern: A mongoc_read_concern_t.
 * @level: The read concern level
 *
 * Sets the read concern level. Any string is supported for future compatability
 * but MongoDB 3.2 only accepts "local" and "majority", aka:
 *  - MONGOC_READ_CONCERN_LEVEL_LOCAL
 *  - MONGOC_READ_CONCERN_LEVEL_MAJORITY
 *
 *  If the @read_concern has already been frozen, calling this function will not
 *  alter the read concern level.
 *
 * See the MongoDB docs for more information on readConcernLevel
 */
bool
mongoc_read_concern_set_level (mongoc_read_concern_t *read_concern,
                               const char            *level)
{
   BSON_ASSERT (read_concern);

   if (read_concern->frozen) {
      return false;
   }

   bson_free (read_concern->level);
   read_concern->level = bson_strdup (level);
   return true;
}
Esempio n. 6
0
mongoc_uri_t *
mongoc_uri_new (const char *uri_string)
{
   mongoc_uri_t *uri;
#ifdef MONGOC_EXPERIMENTAL_FEATURES
   int32_t max_staleness_ms;
#endif

   uri = (mongoc_uri_t *)bson_malloc0(sizeof *uri);
   bson_init(&uri->options);
   bson_init(&uri->credentials);

   /* Initialize read_prefs since tag parsing may add to it */
   uri->read_prefs = mongoc_read_prefs_new(MONGOC_READ_PRIMARY);

   /* Initialize empty read_concern */
   uri->read_concern = mongoc_read_concern_new ();

   if (!uri_string) {
      uri_string = "mongodb://127.0.0.1/";
   }

   if (!mongoc_uri_parse(uri, uri_string)) {
      mongoc_uri_destroy(uri);
      return NULL;
   }

   uri->str = bson_strdup(uri_string);

   _mongoc_uri_assign_read_prefs_mode(uri);
#ifdef MONGOC_EXPERIMENTAL_FEATURES
   max_staleness_ms = mongoc_uri_get_option_as_int32 (uri, "maxstalenessms", 0);
   mongoc_read_prefs_set_max_staleness_ms (uri->read_prefs, max_staleness_ms);
#endif

   if (!mongoc_read_prefs_is_valid(uri->read_prefs)) {
      mongoc_uri_destroy(uri);
      return NULL;
   }

   _mongoc_uri_build_write_concern (uri);

   if (!mongoc_write_concern_is_valid (uri->write_concern)) {
      mongoc_uri_destroy(uri);
      return NULL;
   }

   return uri;
}
Esempio n. 7
0
mongoc_matcher_op_t *
_mongoc_matcher_op_exists_new (const char  *path,   /* IN */
                               bool  exists) /* IN */
{
   mongoc_matcher_op_t *op;

   BSON_ASSERT (path);

   op = bson_malloc0 (sizeof *op);
   op->exists.base.opcode = MONGOC_MATCHER_OPCODE_EXISTS;
   op->exists.path = bson_strdup (path);
   op->exists.exists = exists;

   return op;
}
Esempio n. 8
0
mongoc_matcher_op_t *
_mongoc_matcher_op_not_new (const char          *path,  /* IN */
                            mongoc_matcher_op_t *child) /* IN */
{
   mongoc_matcher_op_t *op;

   BSON_ASSERT (path);
   BSON_ASSERT (child);

   op = bson_malloc0 (sizeof *op);
   op->not.base.opcode = MONGOC_MATCHER_OPCODE_NOT;
   op->not.path = bson_strdup (path);
   op->not.child = child;

   return op;
}
Esempio n. 9
0
char *
_mongoc_sasl_prep (const char *in_utf8, int in_utf8_len, bson_error_t *err)
{
#ifdef MONGOC_ENABLE_ICU
   return _mongoc_sasl_prep_impl ("password", in_utf8, in_utf8_len, err);
#else
   if (_mongoc_sasl_prep_required (in_utf8)) {
      bson_set_error (err,
                      MONGOC_ERROR_SCRAM,
                      MONGOC_ERROR_SCRAM_PROTOCOL_ERROR,
                      "SCRAM Failure: ICU required to SASLPrep password");
      return NULL;
   }
   return bson_strdup (in_utf8);
#endif
}
Esempio n. 10
0
mongoc_matcher_op_t *
_mongoc_matcher_op_type_new (const char  *path, /* IN */
                             bson_type_t  type) /* IN */
{
   mongoc_matcher_op_t *op;

   BSON_ASSERT (path);
   BSON_ASSERT (type);

   op = bson_malloc0 (sizeof *op);
   op->type.base.opcode = MONGOC_MATCHER_OPCODE_TYPE;
   op->type.path = bson_strdup (path);
   op->type.type = type;

   return op;
}
mongoc_write_concern_t *
mongoc_write_concern_copy (const mongoc_write_concern_t *write_concern)
{
   mongoc_write_concern_t *ret = NULL;

   if (write_concern) {
      ret = mongoc_write_concern_new();
      ret->fsync_ = write_concern->fsync_;
      ret->journal = write_concern->journal;
      ret->w = write_concern->w;
      ret->wtimeout = write_concern->wtimeout;
      ret->frozen = false;
      ret->wtag = bson_strdup (write_concern->wtag);
   }

   return ret;
}
Esempio n. 12
0
static bool
mongoc_uri_parse_database (mongoc_uri_t  *uri,
                           const char    *str,
                           const char   **end)
{
   const char *end_database;

   if ((uri->database = scan_to_unichar(str, '?', &end_database))) {
      *end = end_database;
   } else if (*str) {
      uri->database = bson_strdup(str);
      *end = str + strlen(str);
   }

   mongoc_uri_do_unescape(&uri->database);

   return true;
}
Esempio n. 13
0
mongoc_matcher_op_t *
_mongoc_matcher_op_compare_new (mongoc_matcher_opcode_t  opcode, /* IN */
                                const char              *path,   /* IN */
                                const bson_iter_t       *iter)   /* IN */
{
   mongoc_matcher_op_t *op;

   BSON_ASSERT ((opcode >= MONGOC_MATCHER_OPCODE_EQ) &&
                (opcode <= MONGOC_MATCHER_OPCODE_NIN));
   BSON_ASSERT (path);
   BSON_ASSERT (iter);

   op = bson_malloc0 (sizeof *op);
   op->compare.base.opcode = opcode;
   op->compare.path = bson_strdup (path);
   memcpy (&op->compare.iter, iter, sizeof *iter);

   return op;
}
Esempio n. 14
0
char *
_mongoc_hex_md5 (const char *input)
{
   uint8_t digest[16];
   bson_md5_t md5;
   char digest_str[33];
   int i;

   bson_md5_init(&md5);
   bson_md5_append(&md5, (const uint8_t *)input, (uint32_t)strlen(input));
   bson_md5_finish(&md5, digest);

   for (i = 0; i < sizeof digest; i++) {
      bson_snprintf(&digest_str[i*2], 3, "%02x", digest[i]);
   }
   digest_str[sizeof digest_str - 1] = '\0';

   return bson_strdup(digest_str);
}
Esempio n. 15
0
mongoc_uri_t *
mongoc_uri_new (const char *uri_string)
{
   mongoc_uri_t *uri;

   uri = (mongoc_uri_t *)bson_malloc0(sizeof *uri);
   bson_init(&uri->options);
   bson_init(&uri->credentials);

   /* Initialize read_prefs since tag parsing may add to it */
   uri->read_prefs = mongoc_read_prefs_new(MONGOC_READ_PRIMARY);

   /* Initialize empty read_concern */
   uri->read_concern = mongoc_read_concern_new ();

   if (!uri_string) {
      uri_string = "mongodb://127.0.0.1/";
   }

   if (!mongoc_uri_parse(uri, uri_string)) {
      mongoc_uri_destroy(uri);
      return NULL;
   }

   uri->str = bson_strdup(uri_string);

   _mongoc_uri_assign_read_prefs_mode(uri);

   if (!mongoc_read_prefs_is_valid(uri->read_prefs)) {
      mongoc_uri_destroy(uri);
      return NULL;
   }

   _mongoc_uri_build_write_concern (uri);

   if (!mongoc_write_concern_is_valid (uri->write_concern)) {
      mongoc_uri_destroy(uri);
      return NULL;
   }

   return uri;
}
Esempio n. 16
0
bool
mongoc_uri_set_password (mongoc_uri_t *uri, const char *password)
{
   size_t len;

   BSON_ASSERT (password);

   len = strlen(password);

   if (!bson_utf8_validate (password, len, false)) {
      return false;
   }

   if (uri->password) {
      bson_free (uri->password);
   }

   uri->password = bson_strdup (password);
   return true;
}
Esempio n. 17
0
bool
mongoc_uri_set_database (mongoc_uri_t *uri, const char *database)
{
   size_t len;

   BSON_ASSERT (database);

   len = strlen(database);

   if (!bson_utf8_validate (database, len, false)) {
      return false;
   }

   if (uri->database) {
      bson_free (uri->database);
   }

   uri->database = bson_strdup(database);
   return true;
}
Esempio n. 18
0
static mongoc_scram_cache_t *
_mongoc_scram_cache_copy (const mongoc_scram_cache_t *cache)
{
   mongoc_scram_cache_t *ret = NULL;

   if (cache) {
      ret = (mongoc_scram_cache_t *) bson_malloc0 (sizeof (*ret));
      ret->hashed_password = bson_strdup (cache->hashed_password);
      memcpy (
         ret->decoded_salt, cache->decoded_salt, sizeof (ret->decoded_salt));
      ret->iterations = cache->iterations;
      memcpy (ret->client_key, cache->client_key, sizeof (ret->client_key));
      memcpy (ret->server_key, cache->server_key, sizeof (ret->server_key));
      memcpy (ret->salted_password,
              cache->salted_password,
              sizeof (ret->salted_password));
   }

   return ret;
}
Esempio n. 19
0
bool
mongoc_uri_set_username (mongoc_uri_t *uri, const char *username)
{
   size_t len;

   BSON_ASSERT (username);

   len = strlen(username);

   if (!bson_utf8_validate (username, len, false)) {
      return false;
   }

   if (uri->username) {
      bson_free (uri->username);
   }

   uri->username = bson_strdup (username);
   return true;
}
Esempio n. 20
0
bool
_mongoc_host_list_from_string (mongoc_host_list_t *host_list,
                               const char         *host_and_port)
{
   uint16_t port;
   const char *end_host;
   char *hostname = NULL;

   bson_return_val_if_fail(host_list, false);
   bson_return_val_if_fail(host_and_port, false);

   memset(host_list, 0, sizeof *host_list);

   if ((hostname = scan_to_unichar(host_and_port, ':', &end_host))) {
      end_host++;
      if (!isdigit(*end_host)) {
         bson_free(hostname);
         return false;
      }
#ifdef _MSC_VER
      sscanf_s (end_host, "%hu", &port);
#else
      sscanf (end_host, "%hu", &port);
#endif
   } else {
      hostname = bson_strdup(host_and_port);
      port = MONGOC_DEFAULT_PORT;
   }

   bson_strncpy (host_list->host_and_port, host_and_port,
           sizeof host_list->host_and_port - 1);

   bson_strncpy (host_list->host, hostname, sizeof host_list->host - 1);

   host_list->port = port;
   host_list->family = AF_INET;

   bson_free(hostname);

   return true;
}
Esempio n. 21
0
bool
_mongoc_cyrus_set_mechanism (mongoc_cyrus_t *sasl,
                             const char *mechanism,
                             bson_error_t *error)
{
   bson_string_t *str = bson_string_new ("");
   const char **mechs = sasl_global_listmech ();
   int i = 0;
   bool ok = false;

   BSON_ASSERT (sasl);

   for (i = 0; mechs[i]; i++) {
      if (!strcmp (mechs[i], mechanism)) {
         ok = true;
         break;
      }
      bson_string_append (str, mechs[i]);
      if (mechs[i + 1]) {
         bson_string_append (str, ",");
      }
   }

   if (ok) {
      bson_free (sasl->credentials.mechanism);
      sasl->credentials.mechanism = mechanism ? bson_strdup (mechanism) : NULL;
   } else {
      bson_set_error (error,
                      MONGOC_ERROR_SASL,
                      SASL_NOMECH,
                      "SASL Failure: Unsupported mechanism by client: %s. "
                      "Available mechanisms: %s",
                      mechanism,
                      str->str);
   }

   bson_string_free (str, true);
   return ok;
}
Esempio n. 22
0
bson_bool_t
_mongoc_host_list_from_string (mongoc_host_list_t *host_list,
                               const char         *host_and_port)
{
   bson_uint16_t port;
   const char *end_host;
   char *hostname = NULL;

   bson_return_val_if_fail(host_list, FALSE);
   bson_return_val_if_fail(host_and_port, FALSE);

   memset(host_list, 0, sizeof *host_list);

   if ((hostname = scan_to_unichar(host_and_port, ':', &end_host))) {
      end_host++;
      if (!isdigit(*end_host)) {
         bson_free(hostname);
         return FALSE;
      }
      sscanf(end_host, "%hu", &port);
   } else {
      hostname = bson_strdup(host_and_port);
      port = MONGOC_DEFAULT_PORT;
   }

   strncpy(host_list->host_and_port, host_and_port,
           sizeof host_list->host_and_port - 1);
   host_list->host_and_port[sizeof host_list->host_and_port-1] = '\0';

   strncpy(host_list->host, hostname, sizeof host_list->host - 1);
   host_list->host[sizeof host_list->host-1] = '\0';

   host_list->port = port;
   host_list->family = AF_INET;

   bson_free(hostname);

   return TRUE;
}
Esempio n. 23
0
/* Updates the cache with scram's last-used pre-secrets and secrets */
static void
_mongoc_scram_update_cache (mongoc_scram_t *scram)
{
   mongoc_scram_cache_t *cache;

   BSON_ASSERT (scram);

   if (scram->cache) {
      _mongoc_scram_cache_destroy (scram->cache);
   }

   cache = (mongoc_scram_cache_t *) bson_malloc0 (sizeof (*cache));
   cache->hashed_password = bson_strdup (scram->hashed_password);
   memcpy (
      cache->decoded_salt, scram->decoded_salt, sizeof (cache->decoded_salt));
   cache->iterations = scram->iterations;
   memcpy (cache->client_key, scram->client_key, sizeof (cache->client_key));
   memcpy (cache->server_key, scram->server_key, sizeof (cache->server_key));
   memcpy (cache->salted_password,
           scram->salted_password,
           sizeof (cache->salted_password));

   scram->cache = cache;
}
Esempio n. 24
0
mongoc_uri_t *
mongoc_uri_new (const char *uri_string)
{
   mongoc_uri_t *uri;

   uri = bson_malloc0(sizeof *uri);
   bson_init(&uri->options);
   bson_init(&uri->read_prefs);

   if (!uri_string) {
      uri_string = "mongodb://127.0.0.1/";
   }

   if (!mongoc_uri_parse(uri, uri_string)) {
      mongoc_uri_destroy(uri);
      return NULL;
   }

   uri->str = bson_strdup(uri_string);

   _mongoc_uri_build_write_concern (uri);

   return uri;
}
Esempio n. 25
0
/* Parse server-first-message of the form:
 * r=client-nonce|server-nonce,s=user-salt,i=iteration-count
 *
 * Generate client-final-message of the form:
 * c=channel-binding(base64),r=client-nonce|server-nonce,p=client-proof
 */
static bool
_mongoc_scram_step2 (mongoc_scram_t *scram,
                     const uint8_t *inbuf,
                     uint32_t inbuflen,
                     uint8_t *outbuf,
                     uint32_t outbufmax,
                     uint32_t *outbuflen,
                     bson_error_t *error)
{
   uint8_t *val_r = NULL;
   uint32_t val_r_len;
   uint8_t *val_s = NULL;
   uint32_t val_s_len;
   uint8_t *val_i = NULL;
   uint32_t val_i_len;

   uint8_t **current_val;
   uint32_t *current_val_len;

   const uint8_t *ptr;
   const uint8_t *next_comma;

   char *tmp;
   char *hashed_password;

   uint8_t decoded_salt[MONGOC_SCRAM_B64_HASH_SIZE] = {0};
   int32_t decoded_salt_len;
   bool rval = true;

   int iterations;

   BSON_ASSERT (scram);
   BSON_ASSERT (outbuf);
   BSON_ASSERT (outbufmax);
   BSON_ASSERT (outbuflen);

   /* all our passwords go through md5 thanks to MONGODB-CR */
   tmp = bson_strdup_printf ("%s:mongo:%s", scram->user, scram->pass);
   hashed_password = _mongoc_hex_md5 (tmp);
   bson_zero_free (tmp, strlen (tmp));

   /* we need all of the incoming message for the final client proof */
   if (!_mongoc_scram_buf_write ((char *) inbuf,
                                 inbuflen,
                                 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;
   }

   for (ptr = inbuf; ptr < inbuf + inbuflen;) {
      switch (*ptr) {
      case 'r':
         current_val = &val_r;
         current_val_len = &val_r_len;
         break;
      case 's':
         current_val = &val_s;
         current_val_len = &val_s_len;
         break;
      case 'i':
         current_val = &val_i;
         current_val_len = &val_i_len;
         break;
      default:
         bson_set_error (error,
                         MONGOC_ERROR_SCRAM,
                         MONGOC_ERROR_SCRAM_PROTOCOL_ERROR,
                         "SCRAM Failure: unknown key (%c) in sasl step 2",
                         *ptr);
         goto FAIL;
         break;
      }

      ptr++;

      if (*ptr != '=') {
         bson_set_error (error,
                         MONGOC_ERROR_SCRAM,
                         MONGOC_ERROR_SCRAM_PROTOCOL_ERROR,
                         "SCRAM Failure: invalid parse state in sasl step 2");

         goto FAIL;
      }

      ptr++;

      next_comma =
         (const uint8_t *) memchr (ptr, ',', (inbuf + inbuflen) - ptr);

      if (next_comma) {
         *current_val_len = (uint32_t) (next_comma - ptr);
      } else {
         *current_val_len = (uint32_t) ((inbuf + inbuflen) - ptr);
      }

      *current_val = (uint8_t *) bson_malloc (*current_val_len + 1);
      memcpy (*current_val, ptr, *current_val_len);
      (*current_val)[*current_val_len] = '\0';

      if (next_comma) {
         ptr = next_comma + 1;
      } else {
         break;
      }
   }

   if (!val_r) {
      bson_set_error (error,
                      MONGOC_ERROR_SCRAM,
                      MONGOC_ERROR_SCRAM_PROTOCOL_ERROR,
                      "SCRAM Failure: no r param in sasl step 2");

      goto FAIL;
   }

   if (!val_s) {
      bson_set_error (error,
                      MONGOC_ERROR_SCRAM,
                      MONGOC_ERROR_SCRAM_PROTOCOL_ERROR,
                      "SCRAM Failure: no s param in sasl step 2");

      goto FAIL;
   }

   if (!val_i) {
      bson_set_error (error,
                      MONGOC_ERROR_SCRAM,
                      MONGOC_ERROR_SCRAM_PROTOCOL_ERROR,
                      "SCRAM Failure: no i param in sasl step 2");

      goto FAIL;
   }

   /* verify our nonce */
   if (val_r_len < scram->encoded_nonce_len ||
       mongoc_memcmp (val_r, scram->encoded_nonce, scram->encoded_nonce_len)) {
      bson_set_error (
         error,
         MONGOC_ERROR_SCRAM,
         MONGOC_ERROR_SCRAM_PROTOCOL_ERROR,
         "SCRAM Failure: client nonce not repeated in sasl step 2");
   }

   *outbuflen = 0;

   if (!_mongoc_scram_buf_write (
          "c=biws,r=", -1, outbuf, outbufmax, outbuflen)) {
      goto BUFFER;
   }

   if (!_mongoc_scram_buf_write (
          (char *) val_r, val_r_len, outbuf, outbufmax, outbuflen)) {
      goto BUFFER;
   }

   if (!_mongoc_scram_buf_write ((char *) outbuf,
                                 *outbuflen,
                                 scram->auth_message,
                                 scram->auth_messagemax,
                                 &scram->auth_messagelen)) {
      goto BUFFER_AUTH;
   }

   if (!_mongoc_scram_buf_write (",p=", -1, outbuf, outbufmax, outbuflen)) {
      goto BUFFER;
   }

   decoded_salt_len =
      bson_b64_pton ((char *) val_s, decoded_salt, sizeof (decoded_salt));

   if (-1 == decoded_salt_len) {
      bson_set_error (error,
                      MONGOC_ERROR_SCRAM,
                      MONGOC_ERROR_SCRAM_PROTOCOL_ERROR,
                      "SCRAM Failure: unable to decode salt in sasl step2");
      goto FAIL;
   }

   if (16 != decoded_salt_len) {
      bson_set_error (error,
                      MONGOC_ERROR_SCRAM,
                      MONGOC_ERROR_SCRAM_PROTOCOL_ERROR,
                      "SCRAM Failure: invalid salt length of %d in sasl step2",
                      decoded_salt_len);
      goto FAIL;
   }

   iterations = (int) bson_ascii_strtoll ((char *) val_i, &tmp, 10);
   /* tmp holds the location of the failed to parse character.  So if it's
    * null, we got to the end of the string and didn't have a parse error */

   if (*tmp) {
      bson_set_error (
         error,
         MONGOC_ERROR_SCRAM,
         MONGOC_ERROR_SCRAM_PROTOCOL_ERROR,
         "SCRAM Failure: unable to parse iterations in sasl step2");
      goto FAIL;
   }

   if (iterations < 0) {
      bson_set_error (error,
                      MONGOC_ERROR_SCRAM,
                      MONGOC_ERROR_SCRAM_PROTOCOL_ERROR,
                      "SCRAM Failure: iterations is negative in sasl step2");
      goto FAIL;
   }

   /* Save the presecrets for caching */
   scram->hashed_password = bson_strdup (hashed_password);
   scram->iterations = iterations;
   memcpy (scram->decoded_salt, decoded_salt, sizeof (scram->decoded_salt));

   if (scram->cache &&
       _mongoc_scram_cache_has_presecrets (scram->cache, scram)) {
      _mongoc_scram_cache_apply_secrets (scram->cache, scram);
   }

   if (!*scram->salted_password) {
      _mongoc_scram_salt_password (scram,
                                   hashed_password,
                                   (uint32_t) strlen (hashed_password),
                                   decoded_salt,
                                   decoded_salt_len,
                                   (uint32_t) iterations);
   }

   _mongoc_scram_generate_client_proof (scram, outbuf, outbufmax, outbuflen);

   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 step2");

   goto FAIL;

BUFFER:
   bson_set_error (error,
                   MONGOC_ERROR_SCRAM,
                   MONGOC_ERROR_SCRAM_PROTOCOL_ERROR,
                   "SCRAM Failure: could not buffer sasl step2");

   goto FAIL;

FAIL:
   rval = false;

CLEANUP:
   bson_free (val_r);
   bson_free (val_s);
   bson_free (val_i);

   if (hashed_password) {
      bson_zero_free (hashed_password, strlen (hashed_password));
   }

   return rval;
}
Esempio n. 26
0
int
main (int   argc,
      char *argv[])
{
   mongoc_database_t *database = NULL;
   mongoc_client_t *client = NULL;
   mongoc_collection_t *collection = NULL;
   char *host_and_port;
   int res = 0;
   char* other_host_and_port = NULL;

   if (argc < 2 || argc > 3) {
      fprintf (stderr, "usage: %s MONGOD-1-CONNECTION-STRING "
               "[MONGOD-2-HOST-NAME:MONGOD-2-PORT]\n",
               argv[0]);
      fprintf (stderr,
               "MONGOD-1-CONNECTION-STRING can be "
               "of the following forms:\n");
      fprintf (stderr, "localhost\t\t\t\tlocal machine\n");
      fprintf (stderr, "localhost:27018\t\t\t\tlocal machine on port 27018\n");
      fprintf (stderr,
               "mongodb://*****:*****@localhost:27017\t"
               "local machine on port 27017, and authenticate with username "
               "user and password pass\n");
      return 1;
   }

   mongoc_init ();

   if (strncmp (argv[1], "mongodb://", 10) == 0) {
      host_and_port = bson_strdup (argv [1]);
   } else {
      host_and_port = bson_strdup_printf ("mongodb://%s", argv[1]);
   }
   other_host_and_port = argc > 2 ? argv[2] : NULL;

   client = mongoc_client_new (host_and_port);

   if (!client) {
      fprintf(stderr, "Invalid hostname or port: %s\n", host_and_port);
      res = 2;
      goto cleanup;
   }

   database = mongoc_client_get_database (client, "test");
   collection = mongoc_database_get_collection (database, COLLECTION_NAME);

   printf ("Inserting data\n");
   if (!insert_data (collection)) {
      res = 3;
      goto cleanup;
   }

   printf ("explain\n");
   if (!explain (collection)) {
      res = 4;
      goto cleanup;
   }

   if (other_host_and_port) {
      printf ("copydb\n");
      if (!copydb (client, other_host_and_port)) {
         res = 5;
         goto cleanup;
      }

      printf ("clone collection\n");
      if (!clone_collection (database, other_host_and_port)) {
         res = 6;
         goto cleanup;
      }
   }

cleanup:
   if (collection) {
      mongoc_collection_destroy (collection);
   }

   if (database) {
      mongoc_database_destroy (database);
   }

   if (client) {
      mongoc_client_destroy (client);
   }

   bson_free (host_and_port);
   mongoc_cleanup ();
   return res;
}
Esempio n. 27
0
/* Parse server-first-message of the form:
 * r=client-nonce|server-nonce,s=user-salt,i=iteration-count
 *
 * Generate client-final-message of the form:
 * c=channel-binding(base64),r=client-nonce|server-nonce,p=client-proof
 */
static bool
_mongoc_scram_step2 (mongoc_scram_t *scram,
                     const uint8_t *inbuf,
                     uint32_t inbuflen,
                     uint8_t *outbuf,
                     uint32_t outbufmax,
                     uint32_t *outbuflen,
                     bson_error_t *error)
{
   uint8_t *val_r = NULL;
   uint32_t val_r_len;
   uint8_t *val_s = NULL;
   uint32_t val_s_len;
   uint8_t *val_i = NULL;
   uint32_t val_i_len;

   uint8_t **current_val;
   uint32_t *current_val_len;

   const uint8_t *ptr;
   const uint8_t *next_comma;

   char *tmp;
   char *hashed_password;

   uint8_t decoded_salt[MONGOC_SCRAM_B64_HASH_MAX_SIZE] = {0};
   int32_t decoded_salt_len;
   /* the decoded salt leaves four trailing bytes to add the int32 0x00000001 */
   const int32_t expected_salt_length = _scram_hash_size (scram) - 4;
   bool rval = true;

   int iterations;


   BSON_ASSERT (scram);
   BSON_ASSERT (outbuf);
   BSON_ASSERT (outbufmax);
   BSON_ASSERT (outbuflen);

   if (scram->crypto.algorithm == MONGOC_CRYPTO_ALGORITHM_SHA_1) {
      /* Auth spec for SCRAM-SHA-1: "The password variable MUST be the mongodb
       * hashed variant. The mongo hashed variant is computed as hash = HEX(
       * MD5( UTF8( username + ':mongo:' + plain_text_password )))" */
      tmp = bson_strdup_printf ("%s:mongo:%s", scram->user, scram->pass);
      hashed_password = _mongoc_hex_md5 (tmp);
      bson_zero_free (tmp, strlen (tmp));
   } else if (scram->crypto.algorithm == MONGOC_CRYPTO_ALGORITHM_SHA_256) {
      /* Auth spec for SCRAM-SHA-256: "Passwords MUST be prepared with SASLprep,
       * per RFC 5802. Passwords are used directly for key derivation; they
       * MUST NOT be digested as they are in SCRAM-SHA-1." */
      hashed_password =
         _mongoc_sasl_prep (scram->pass, (int) strlen (scram->pass), error);
      if (!hashed_password) {
         goto FAIL;
      }
   } else {
      BSON_ASSERT (false);
   }

   /* we need all of the incoming message for the final client proof */
   if (!_mongoc_scram_buf_write ((char *) inbuf,
                                 inbuflen,
                                 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;
   }

   for (ptr = inbuf; ptr < inbuf + inbuflen;) {
      switch (*ptr) {
      case 'r':
         current_val = &val_r;
         current_val_len = &val_r_len;
         break;
      case 's':
         current_val = &val_s;
         current_val_len = &val_s_len;
         break;
      case 'i':
         current_val = &val_i;
         current_val_len = &val_i_len;
         break;
      default:
         bson_set_error (error,
                         MONGOC_ERROR_SCRAM,
                         MONGOC_ERROR_SCRAM_PROTOCOL_ERROR,
                         "SCRAM Failure: unknown key (%c) in sasl step 2",
                         *ptr);
         goto FAIL;
      }

      ptr++;

      if (*ptr != '=') {
         bson_set_error (error,
                         MONGOC_ERROR_SCRAM,
                         MONGOC_ERROR_SCRAM_PROTOCOL_ERROR,
                         "SCRAM Failure: invalid parse state in sasl step 2");

         goto FAIL;
      }

      ptr++;

      next_comma =
         (const uint8_t *) memchr (ptr, ',', (inbuf + inbuflen) - ptr);

      if (next_comma) {
         *current_val_len = (uint32_t) (next_comma - ptr);
      } else {
         *current_val_len = (uint32_t) ((inbuf + inbuflen) - ptr);
      }

      *current_val = (uint8_t *) bson_malloc (*current_val_len + 1);
      memcpy (*current_val, ptr, *current_val_len);
      (*current_val)[*current_val_len] = '\0';

      if (next_comma) {
         ptr = next_comma + 1;
      } else {
         break;
      }
   }

   if (!val_r) {
      bson_set_error (error,
                      MONGOC_ERROR_SCRAM,
                      MONGOC_ERROR_SCRAM_PROTOCOL_ERROR,
                      "SCRAM Failure: no r param in sasl step 2");

      goto FAIL;
   }

   if (!val_s) {
      bson_set_error (error,
                      MONGOC_ERROR_SCRAM,
                      MONGOC_ERROR_SCRAM_PROTOCOL_ERROR,
                      "SCRAM Failure: no s param in sasl step 2");

      goto FAIL;
   }

   if (!val_i) {
      bson_set_error (error,
                      MONGOC_ERROR_SCRAM,
                      MONGOC_ERROR_SCRAM_PROTOCOL_ERROR,
                      "SCRAM Failure: no i param in sasl step 2");

      goto FAIL;
   }

   /* verify our nonce */
   if (val_r_len < scram->encoded_nonce_len ||
       mongoc_memcmp (val_r, scram->encoded_nonce, scram->encoded_nonce_len)) {
      bson_set_error (
         error,
         MONGOC_ERROR_SCRAM,
         MONGOC_ERROR_SCRAM_PROTOCOL_ERROR,
         "SCRAM Failure: client nonce not repeated in sasl step 2");
   }

   *outbuflen = 0;

   if (!_mongoc_scram_buf_write (
          "c=biws,r=", -1, outbuf, outbufmax, outbuflen)) {
      goto BUFFER;
   }

   if (!_mongoc_scram_buf_write (
          (char *) val_r, val_r_len, outbuf, outbufmax, outbuflen)) {
      goto BUFFER;
   }

   if (!_mongoc_scram_buf_write ((char *) outbuf,
                                 *outbuflen,
                                 scram->auth_message,
                                 scram->auth_messagemax,
                                 &scram->auth_messagelen)) {
      goto BUFFER_AUTH;
   }

   if (!_mongoc_scram_buf_write (",p=", -1, outbuf, outbufmax, outbuflen)) {
      goto BUFFER;
   }

   decoded_salt_len =
      bson_b64_pton ((char *) val_s, decoded_salt, sizeof (decoded_salt));

   if (-1 == decoded_salt_len) {
      bson_set_error (error,
                      MONGOC_ERROR_SCRAM,
                      MONGOC_ERROR_SCRAM_PROTOCOL_ERROR,
                      "SCRAM Failure: unable to decode salt in sasl step2");
      goto FAIL;
   }

   if (expected_salt_length != decoded_salt_len) {
      bson_set_error (error,
                      MONGOC_ERROR_SCRAM,
                      MONGOC_ERROR_SCRAM_PROTOCOL_ERROR,
                      "SCRAM Failure: invalid salt length of %d in sasl step2",
                      decoded_salt_len);
      goto FAIL;
   }

   iterations = (int) bson_ascii_strtoll ((char *) val_i, &tmp, 10);
   /* tmp holds the location of the failed to parse character.  So if it's
    * null, we got to the end of the string and didn't have a parse error */

   if (*tmp) {
      bson_set_error (
         error,
         MONGOC_ERROR_SCRAM,
         MONGOC_ERROR_SCRAM_PROTOCOL_ERROR,
         "SCRAM Failure: unable to parse iterations in sasl step2");
      goto FAIL;
   }

   if (iterations < 0) {
      bson_set_error (error,
                      MONGOC_ERROR_SCRAM,
                      MONGOC_ERROR_SCRAM_PROTOCOL_ERROR,
                      "SCRAM Failure: iterations is negative in sasl step2");
      goto FAIL;
   }

   /* drivers MUST enforce a minimum iteration count of 4096 and MUST error if
    * the authentication conversation specifies a lower count. This mitigates
    * downgrade attacks by a man-in-the-middle attacker. */
   if (iterations < 4096) {
      bson_set_error (error,
                      MONGOC_ERROR_SCRAM,
                      MONGOC_ERROR_SCRAM_PROTOCOL_ERROR,
                      "SCRAM Failure: iterations must be at least 4096");
      goto FAIL;
   }

   /* Save the presecrets for caching */
   scram->hashed_password = bson_strdup (hashed_password);
   scram->iterations = iterations;
   memcpy (scram->decoded_salt, decoded_salt, sizeof (scram->decoded_salt));

   if (scram->cache &&
       _mongoc_scram_cache_has_presecrets (scram->cache, scram)) {
      _mongoc_scram_cache_apply_secrets (scram->cache, scram);
   }

   if (!*scram->salted_password) {
      _mongoc_scram_salt_password (scram,
                                   hashed_password,
                                   (uint32_t) strlen (hashed_password),
                                   decoded_salt,
                                   decoded_salt_len,
                                   (uint32_t) iterations);
   }

   _mongoc_scram_generate_client_proof (scram, outbuf, outbufmax, outbuflen);

   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 step2");

   goto FAIL;

BUFFER:
   bson_set_error (error,
                   MONGOC_ERROR_SCRAM,
                   MONGOC_ERROR_SCRAM_PROTOCOL_ERROR,
                   "SCRAM Failure: could not buffer sasl step2");

   goto FAIL;

FAIL:
   rval = false;

CLEANUP:
   bson_free (val_r);
   bson_free (val_s);
   bson_free (val_i);

   if (hashed_password) {
      bson_zero_free (hashed_password, strlen (hashed_password));
   }

   return rval;
}
Esempio n. 28
0
/**
 * _mongoc_gridfs_file_new:
 *
 * Create a new empty gridfs file
 */
mongoc_gridfs_file_t *
_mongoc_gridfs_file_new (mongoc_gridfs_t *gridfs, mongoc_gridfs_file_opt_t *opt)
{
   mongoc_gridfs_file_t *file;
   mongoc_gridfs_file_opt_t default_opt = {0};

   ENTRY;

   BSON_ASSERT (gridfs);

   if (!opt) {
      opt = &default_opt;
   }

   file = (mongoc_gridfs_file_t *) bson_malloc0 (sizeof *file);

   file->gridfs = gridfs;
   file->is_dirty = 1;

   if (opt->chunk_size) {
      file->chunk_size = opt->chunk_size;
   } else {
      /*
       * The default chunk size is now 255kb. This used to be 256k but has been
       * reduced to allow for them to fit within power of two sizes in mongod.
       *
       * See CDRIVER-322.
       */
      file->chunk_size = (1 << 18) - 1024;
   }

   file->files_id.value_type = BSON_TYPE_OID;
   bson_oid_init (&file->files_id.value.v_oid, NULL);

   file->upload_date = ((int64_t) time (NULL)) * 1000;

   if (opt->md5) {
      file->md5 = bson_strdup (opt->md5);
   }

   if (opt->filename) {
      file->filename = bson_strdup (opt->filename);
   }

   if (opt->content_type) {
      file->content_type = bson_strdup (opt->content_type);
   }

   if (opt->aliases) {
      bson_copy_to (opt->aliases, &(file->aliases));
   }

   if (opt->metadata) {
      bson_copy_to (opt->metadata, &(file->metadata));
   }

   file->pos = 0;
   file->n = 0;

   RETURN (file);
}
Esempio n. 29
0
void
ha_sharded_cluster_start (ha_sharded_cluster_t *cluster)
{
   bson_string_t *configopt;
   struct stat st;
   ha_node_t *iter;
   char *cmd;
   int i;

   bson_return_if_fail(cluster);

   if (!stat(cluster->name, &st)) {
      if (S_ISDIR(st.st_mode)) {
         /* Ayyyeeeeeee */
         cmd = bson_strdup_printf("rm -rf \"%s\"", cluster->name);
         fprintf(stderr, "%s\n", cmd);
         system(cmd);
         bson_free(cmd);
      }
   }

   if (!!mkdir(cluster->name, 0750)) {
      fprintf(stderr, "Failed to create directory \"%s\"\n",
              cluster->name);
      abort();
   }

   for (i = 0; i < 12; i++) {
      if (cluster->replicas[i]) {
         ha_replica_set_start(cluster->replicas[i]);
      }
   }

   configopt = bson_string_new (NULL);

   for (iter = cluster->configs; iter; iter = iter->next) {
      ha_node_setup(iter);
      ha_node_restart(iter);
      bson_string_append_printf (configopt, "127.0.0.1:%hu%s",
                                 iter->port,
                                 iter->next ? "," : "");
   }

   sleep (5);

   for (iter = cluster->routers; iter; iter = iter->next) {
      bson_free (iter->configopt);
      iter->configopt = bson_strdup (configopt->str);
      ha_node_setup (iter);
      ha_node_restart (iter);
   }

   ha_sharded_cluster_wait_for_healthy (cluster);

   for (i = 0; i < 12; i++) {
      if (cluster->replicas[i]) {
         ha_config_add_shard (cluster->routers, cluster->replicas[i]);
      }
   }

   bson_string_free (configopt, TRUE);
}
Esempio n. 30
0
static bool
mongoc_uri_parse_option (mongoc_uri_t *uri,
                         const char   *str)
{
   int32_t v_int;
   const char *end_key;
   char *key = NULL;
   char *value = NULL;
   bool ret = false;

   if (!(key = scan_to_unichar(str, '=', "", &end_key))) {
      goto CLEANUP;
   }

   value = bson_strdup(end_key + 1);
   mongoc_uri_do_unescape(&value);
   if (!value) {
      /* do_unescape detected invalid UTF-8 and freed value */
      goto CLEANUP;
   }

   if (mongoc_uri_option_is_int32(key)) {
      v_int = (int) strtol (value, NULL, 10);
      BSON_APPEND_INT32 (&uri->options, key, v_int);
   } else if (!strcasecmp(key, "w")) {
      if (*value == '-' || isdigit(*value)) {
         v_int = (int) strtol (value, NULL, 10);
         BSON_APPEND_INT32 (&uri->options, "w", v_int);
      } else if (0 == strcasecmp (value, "majority")) {
         BSON_APPEND_UTF8 (&uri->options, "w", "majority");
      } else if (*value) {
         BSON_APPEND_UTF8 (&uri->options, "w", value);
      }
   } else if (mongoc_uri_option_is_bool(key)) {
      bson_append_bool (&uri->options, key, -1,
                        (0 == strcasecmp (value, "true")) ||
                        (0 == strcasecmp (value, "t")) ||
                        (0 == strcmp (value, "1")));
   } else if (!strcasecmp(key, "readpreferencetags")) {
      mongoc_uri_parse_tags(uri, value);
   } else if (!strcasecmp(key, "authmechanism") ||
              !strcasecmp(key, "authsource")) {
      bson_append_utf8(&uri->credentials, key, -1, value, -1);
   } else if (!strcasecmp(key, "readconcernlevel")) {
      mongoc_read_concern_set_level (uri->read_concern, value);
   } else if (!strcasecmp(key, "authmechanismproperties")) {
      if (!mongoc_uri_parse_auth_mechanism_properties(uri, value)) {
         goto CLEANUP;
      }
#ifdef MONGOC_EXPERIMENTAL_FEATURES
   } else if (!strcasecmp (key, "appname")) {
      if (!mongoc_uri_set_appname (uri, value)) {
         MONGOC_WARNING ("Cannot set appname: %s is invalid", value);
         goto CLEANUP;
      }
#endif
   } else {
      bson_append_utf8(&uri->options, key, -1, value, -1);
   }

   ret = true;

CLEANUP:
   bson_free(key);
   bson_free(value);

   return ret;
}