You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by ga...@apache.org on 2015/10/14 12:09:20 UTC

[23/52] [partial] couchdb-nmo git commit: prepare for release

http://git-wip-us.apache.org/repos/asf/couchdb-nmo/blob/753f1767/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/kerberos.js
----------------------------------------------------------------------
diff --git a/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/kerberos.js b/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/kerberos.js
new file mode 100644
index 0000000..c7bae58
--- /dev/null
+++ b/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/kerberos.js
@@ -0,0 +1,164 @@
+var kerberos = require('../build/Release/kerberos')
+  , KerberosNative = kerberos.Kerberos;
+
+var Kerberos = function() {
+  this._native_kerberos = new KerberosNative(); 
+}
+
+// callback takes two arguments, an error string if defined and a new context
+// uri should be given as service@host.  Services are not always defined
+// in a straightforward way.  Use 'HTTP' for SPNEGO / Negotiate authentication. 
+Kerberos.prototype.authGSSClientInit = function(uri, flags, callback) {
+  return this._native_kerberos.authGSSClientInit(uri, flags, callback);
+}
+
+// This will obtain credentials using a credentials cache. To override the default
+// location (posible /tmp/krb5cc_nnnnnn, where nnnn is your numeric uid) use 
+// the environment variable KRB5CNAME. 
+// The credentials (suitable for using in an 'Authenticate: ' header, when prefixed
+// with 'Negotiate ') will be available as context.response inside the callback
+// if no error is indicated.
+// callback takes one argument, an error string if defined
+Kerberos.prototype.authGSSClientStep = function(context, challenge, callback) {
+  if(typeof challenge == 'function') {
+    callback = challenge;
+    challenge = '';
+  }
+
+  return this._native_kerberos.authGSSClientStep(context, challenge, callback);
+}
+
+Kerberos.prototype.authGSSClientUnwrap = function(context, challenge, callback) {
+  if(typeof challenge == 'function') {
+    callback = challenge;
+    challenge = '';
+  }
+
+  return this._native_kerberos.authGSSClientUnwrap(context, challenge, callback);
+}
+
+Kerberos.prototype.authGSSClientWrap = function(context, challenge, user_name, callback) {
+  if(typeof user_name == 'function') {
+    callback = user_name;
+    user_name = '';
+  }
+
+  return this._native_kerberos.authGSSClientWrap(context, challenge, user_name, callback);
+}
+
+// free memory used by a context created using authGSSClientInit.
+// callback takes one argument, an error string if defined.
+Kerberos.prototype.authGSSClientClean = function(context, callback) {
+  return this._native_kerberos.authGSSClientClean(context, callback);
+}
+
+// The server will obtain credentials using a keytab.  To override the 
+// default location (probably /etc/krb5.keytab) set the KRB5_KTNAME
+// environment variable.
+// The service name should be in the form service, or service@host.name
+// e.g. for HTTP, use "HTTP" or "HTTP@my.host.name". See gss_import_name
+// for GSS_C_NT_HOSTBASED_SERVICE.
+//
+// a boolean turns on "constrained_delegation". this enables acquisition of S4U2Proxy 
+// credentials which will be stored in a credentials cache during the authGSSServerStep
+// method. this parameter is optional.
+//
+// when "constrained_delegation" is enabled, a username can (optionally) be provided and
+// S4U2Self protocol transition will be initiated. In this case, we will not
+// require any "auth" data during the authGSSServerStep. This parameter is optional
+// but constrained_delegation MUST be enabled for this to work. When S4U2Self is
+// used, the username will be assumed to have been already authenticated, and no
+// actual authentication will be performed. This is basically a way to "bootstrap"
+// kerberos credentials (which can then be delegated with S4U2Proxy) for a user
+// authenticated externally.
+//
+// callback takes two arguments, an error string if defined and a new context
+//
+Kerberos.prototype.authGSSServerInit = function(service, constrained_delegation, username, callback) {
+  if(typeof(constrained_delegation) === 'function') {
+	  callback = constrained_delegation;
+	  constrained_delegation = false;
+	  username = null;
+  }
+
+  if (typeof(constrained_delegation) === 'string') {
+	  throw new Error("S4U2Self protocol transation is not possible without enabling constrained delegation");
+  }
+
+  if (typeof(username) === 'function') {
+	  callback = username;
+	  username = null;
+  }
+
+  constrained_delegation = !!constrained_delegation;
+  
+  return this._native_kerberos.authGSSServerInit(service, constrained_delegation, username, callback);
+};
+
+//callback takes one argument, an error string if defined.
+Kerberos.prototype.authGSSServerClean = function(context, callback) {
+  return this._native_kerberos.authGSSServerClean(context, callback);
+};
+
+// authData should be the base64 encoded authentication data obtained
+// from client, e.g., in the Authorization header (without the leading 
+// "Negotiate " string) during SPNEGO authentication.  The authenticated user 
+// is available in context.username after successful authentication.
+// callback takes one argument, an error string if defined.
+//
+// Note: when S4U2Self protocol transition was requested in the authGSSServerInit
+// no actual authentication will be performed and authData will be ignored.
+//
+Kerberos.prototype.authGSSServerStep = function(context, authData, callback) {
+  return this._native_kerberos.authGSSServerStep(context, authData, callback);
+};
+
+Kerberos.prototype.acquireAlternateCredentials = function(user_name, password, domain) {
+  return this._native_kerberos.acquireAlternateCredentials(user_name, password, domain); 
+}
+
+Kerberos.prototype.prepareOutboundPackage = function(principal, inputdata) {
+  return this._native_kerberos.prepareOutboundPackage(principal, inputdata); 
+}
+
+Kerberos.prototype.decryptMessage = function(challenge) {
+  return this._native_kerberos.decryptMessage(challenge);
+}
+
+Kerberos.prototype.encryptMessage = function(challenge) {
+  return this._native_kerberos.encryptMessage(challenge); 
+}
+
+Kerberos.prototype.queryContextAttribute = function(attribute) {
+  if(typeof attribute != 'number' && attribute != 0x00) throw new Error("Attribute not supported");
+  return this._native_kerberos.queryContextAttribute(attribute);
+}
+
+// Some useful result codes
+Kerberos.AUTH_GSS_CONTINUE     = 0;
+Kerberos.AUTH_GSS_COMPLETE     = 1;
+     
+// Some useful gss flags 
+Kerberos.GSS_C_DELEG_FLAG      = 1;
+Kerberos.GSS_C_MUTUAL_FLAG     = 2;
+Kerberos.GSS_C_REPLAY_FLAG     = 4;
+Kerberos.GSS_C_SEQUENCE_FLAG   = 8;
+Kerberos.GSS_C_CONF_FLAG       = 16; 
+Kerberos.GSS_C_INTEG_FLAG      = 32;
+Kerberos.GSS_C_ANON_FLAG       = 64;
+Kerberos.GSS_C_PROT_READY_FLAG = 128; 
+Kerberos.GSS_C_TRANS_FLAG      = 256;
+
+// Export Kerberos class
+exports.Kerberos = Kerberos;
+
+// If we have SSPI (windows)
+if(kerberos.SecurityCredentials) {
+  // Put all SSPI classes in it's own namespace
+  exports.SSIP = {
+      SecurityCredentials: require('./win32/wrappers/security_credentials').SecurityCredentials
+    , SecurityContext: require('./win32/wrappers/security_context').SecurityContext
+    , SecurityBuffer: require('./win32/wrappers/security_buffer').SecurityBuffer
+    , SecurityBufferDescriptor: require('./win32/wrappers/security_buffer_descriptor').SecurityBufferDescriptor
+  }
+}

http://git-wip-us.apache.org/repos/asf/couchdb-nmo/blob/753f1767/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/kerberos_context.cc
----------------------------------------------------------------------
diff --git a/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/kerberos_context.cc b/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/kerberos_context.cc
new file mode 100644
index 0000000..bf24118
--- /dev/null
+++ b/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/kerberos_context.cc
@@ -0,0 +1,134 @@
+#include "kerberos_context.h"
+
+Nan::Persistent<FunctionTemplate> KerberosContext::constructor_template;
+
+KerberosContext::KerberosContext() : Nan::ObjectWrap() {
+    state = NULL;
+    server_state = NULL;
+}
+
+KerberosContext::~KerberosContext() {
+}
+
+KerberosContext* KerberosContext::New() {
+  Nan::HandleScope scope;
+  Local<Object> obj = Nan::New(constructor_template)->GetFunction()->NewInstance();
+  KerberosContext *kerberos_context = Nan::ObjectWrap::Unwrap<KerberosContext>(obj);
+  return kerberos_context;
+}
+
+NAN_METHOD(KerberosContext::New) {
+  // Create code object
+  KerberosContext *kerberos_context = new KerberosContext();
+  // Wrap it
+  kerberos_context->Wrap(info.This());
+  // Return the object
+  info.GetReturnValue().Set(info.This());
+}
+
+void KerberosContext::Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target) {
+  // Grab the scope of the call from Node
+  Nan::HandleScope scope;
+
+  // Define a new function template
+  Local<FunctionTemplate> t = Nan::New<v8::FunctionTemplate>(static_cast<NAN_METHOD((*))>(New));
+  t->InstanceTemplate()->SetInternalFieldCount(1);
+  t->SetClassName(Nan::New<String>("KerberosContext").ToLocalChecked());
+
+  // Get prototype
+  Local<ObjectTemplate> proto = t->PrototypeTemplate();
+
+  // Getter for the response
+  Nan::SetAccessor(proto, Nan::New<String>("response").ToLocalChecked(), KerberosContext::ResponseGetter);
+
+  // Getter for the username
+  Nan::SetAccessor(proto, Nan::New<String>("username").ToLocalChecked(), KerberosContext::UsernameGetter);
+
+  // Getter for the targetname - server side only
+  Nan::SetAccessor(proto, Nan::New<String>("targetname").ToLocalChecked(), KerberosContext::TargetnameGetter);
+
+  Nan::SetAccessor(proto, Nan::New<String>("delegatedCredentialsCache").ToLocalChecked(), KerberosContext::DelegatedCredentialsCacheGetter);
+
+  // Set persistent
+  constructor_template.Reset(t);
+ // NanAssignPersistent(constructor_template, t);
+
+  // Set the symbol
+  target->ForceSet(Nan::New<String>("KerberosContext").ToLocalChecked(), t->GetFunction());
+}
+
+
+// Response Setter / Getter
+NAN_GETTER(KerberosContext::ResponseGetter) {
+  gss_client_state *client_state;
+  gss_server_state *server_state;
+
+  // Unpack the object
+  KerberosContext *context = Nan::ObjectWrap::Unwrap<KerberosContext>(info.This());
+
+  // Response could come from client or server state...
+  client_state = context->state;
+  server_state = context->server_state;
+
+  // If client state is in use, take response from there, otherwise from server
+  char *response = client_state != NULL ? client_state->response :
+	  server_state != NULL ? server_state->response : NULL;
+
+  if(response == NULL) {
+    info.GetReturnValue().Set(Nan::Null());
+  } else {
+    // Return the response
+    info.GetReturnValue().Set(Nan::New<String>(response).ToLocalChecked());
+  }
+}
+
+// username Getter
+NAN_GETTER(KerberosContext::UsernameGetter) {
+  // Unpack the object
+  KerberosContext *context = Nan::ObjectWrap::Unwrap<KerberosContext>(info.This());
+
+  gss_client_state *client_state = context->state;
+  gss_server_state *server_state = context->server_state;
+
+  // If client state is in use, take response from there, otherwise from server
+  char *username = client_state != NULL ? client_state->username :
+	  server_state != NULL ? server_state->username : NULL;
+
+  if(username == NULL) {
+    info.GetReturnValue().Set(Nan::Null());
+  } else {
+    info.GetReturnValue().Set(Nan::New<String>(username).ToLocalChecked());
+  }
+}
+
+// targetname Getter - server side only
+NAN_GETTER(KerberosContext::TargetnameGetter) {
+  // Unpack the object
+  KerberosContext *context = Nan::ObjectWrap::Unwrap<KerberosContext>(info.This());
+
+  gss_server_state *server_state = context->server_state;
+
+  char *targetname = server_state != NULL ? server_state->targetname : NULL;
+
+  if(targetname == NULL) {
+    info.GetReturnValue().Set(Nan::Null());
+  } else {
+    info.GetReturnValue().Set(Nan::New<String>(targetname).ToLocalChecked());
+  }
+}
+
+// targetname Getter - server side only
+NAN_GETTER(KerberosContext::DelegatedCredentialsCacheGetter) {
+  // Unpack the object
+  KerberosContext *context = Nan::ObjectWrap::Unwrap<KerberosContext>(info.This());
+
+  gss_server_state *server_state = context->server_state;
+
+  char *delegated_credentials_cache = server_state != NULL ? server_state->delegated_credentials_cache : NULL;
+
+  if(delegated_credentials_cache == NULL) {
+    info.GetReturnValue().Set(Nan::Null());
+  } else {
+    info.GetReturnValue().Set(Nan::New<String>(delegated_credentials_cache).ToLocalChecked());
+  }
+}

http://git-wip-us.apache.org/repos/asf/couchdb-nmo/blob/753f1767/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/kerberos_context.h
----------------------------------------------------------------------
diff --git a/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/kerberos_context.h b/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/kerberos_context.h
new file mode 100644
index 0000000..23eb577
--- /dev/null
+++ b/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/kerberos_context.h
@@ -0,0 +1,64 @@
+#ifndef KERBEROS_CONTEXT_H
+#define KERBEROS_CONTEXT_H
+
+#include <node.h>
+#include <gssapi/gssapi.h>
+#include <gssapi/gssapi_generic.h>
+#include <gssapi/gssapi_krb5.h>
+
+#include "nan.h"
+#include <node_object_wrap.h>
+#include <v8.h>
+
+extern "C" {
+  #include "kerberosgss.h"
+}
+
+using namespace v8;
+using namespace node;
+
+class KerberosContext : public Nan::ObjectWrap {
+
+public:
+  KerberosContext();
+  ~KerberosContext();
+
+  static inline bool HasInstance(Local<Value> val) {
+    if (!val->IsObject()) return false;
+    Local<Object> obj = val->ToObject();
+    return Nan::New(constructor_template)->HasInstance(obj);
+  };
+
+  inline bool IsClientInstance() {
+      return state != NULL;
+  }
+
+  inline bool IsServerInstance() {
+      return server_state != NULL;
+  }
+
+  // Constructor used for creating new Kerberos objects from C++
+  static Nan::Persistent<FunctionTemplate> constructor_template;
+
+  // Initialize function for the object
+  static void Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target);
+
+  // Public constructor
+  static KerberosContext* New();
+
+  // Handle to the kerberos client context
+  gss_client_state *state;
+
+  // Handle to the kerberos server context
+  gss_server_state *server_state;
+
+private:
+  static NAN_METHOD(New);
+  // In either client state or server state
+  static NAN_GETTER(ResponseGetter);
+  static NAN_GETTER(UsernameGetter);
+  // Only in the "server_state"
+  static NAN_GETTER(TargetnameGetter);
+  static NAN_GETTER(DelegatedCredentialsCacheGetter);
+};
+#endif

http://git-wip-us.apache.org/repos/asf/couchdb-nmo/blob/753f1767/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/kerberosgss.c
----------------------------------------------------------------------
diff --git a/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/kerberosgss.c b/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/kerberosgss.c
new file mode 100644
index 0000000..2fbca00
--- /dev/null
+++ b/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/kerberosgss.c
@@ -0,0 +1,931 @@
+/**
+ * Copyright (c) 2006-2010 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ **/
+/*
+ * S4U2Proxy implementation
+ * Copyright (C) 2015 David Mansfield
+ * Code inspired by mod_auth_kerb.
+ */
+
+#include "kerberosgss.h"
+
+#include "base64.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <krb5.h>
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+
+void die1(const char *message) {
+  if(errno) {
+    perror(message);
+  } else {
+    printf("ERROR: %s\n", message);
+  }
+
+  exit(1);
+}
+
+static gss_client_response *gss_error(const char *func, const char *op, OM_uint32 err_maj, OM_uint32 err_min);
+static gss_client_response *other_error(const char *fmt, ...);
+static gss_client_response *krb5_ctx_error(krb5_context context, krb5_error_code problem);
+
+static gss_client_response *store_gss_creds(gss_server_state *state);
+static gss_client_response *create_krb5_ccache(gss_server_state *state, krb5_context context, krb5_principal princ, krb5_ccache *ccache);
+
+/*
+char* server_principal_details(const char* service, const char* hostname)
+{
+    char match[1024];
+    int match_len = 0;
+    char* result = NULL;
+    
+    int code;
+    krb5_context kcontext;
+    krb5_keytab kt = NULL;
+    krb5_kt_cursor cursor = NULL;
+    krb5_keytab_entry entry;
+    char* pname = NULL;
+    
+    // Generate the principal prefix we want to match
+    snprintf(match, 1024, "%s/%s@", service, hostname);
+    match_len = strlen(match);
+    
+    code = krb5_init_context(&kcontext);
+    if (code)
+    {
+        PyErr_SetObject(KrbException_class, Py_BuildValue("((s:i))",
+                                                          "Cannot initialize Kerberos5 context", code));
+        return NULL;
+    }
+    
+    if ((code = krb5_kt_default(kcontext, &kt)))
+    {
+        PyErr_SetObject(KrbException_class, Py_BuildValue("((s:i))",
+                                                          "Cannot get default keytab", code));
+        goto end;
+    }
+    
+    if ((code = krb5_kt_start_seq_get(kcontext, kt, &cursor)))
+    {
+        PyErr_SetObject(KrbException_class, Py_BuildValue("((s:i))",
+                                                          "Cannot get sequence cursor from keytab", code));
+        goto end;
+    }
+    
+    while ((code = krb5_kt_next_entry(kcontext, kt, &entry, &cursor)) == 0)
+    {
+        if ((code = krb5_unparse_name(kcontext, entry.principal, &pname)))
+        {
+            PyErr_SetObject(KrbException_class, Py_BuildValue("((s:i))",
+                                                              "Cannot parse principal name from keytab", code));
+            goto end;
+        }
+        
+        if (strncmp(pname, match, match_len) == 0)
+        {
+            result = malloc(strlen(pname) + 1);
+            strcpy(result, pname);
+            krb5_free_unparsed_name(kcontext, pname);
+            krb5_free_keytab_entry_contents(kcontext, &entry);
+            break;
+        }
+        
+        krb5_free_unparsed_name(kcontext, pname);
+        krb5_free_keytab_entry_contents(kcontext, &entry);
+    }
+    
+    if (result == NULL)
+    {
+        PyErr_SetObject(KrbException_class, Py_BuildValue("((s:i))",
+                                                          "Principal not found in keytab", -1));
+    }
+    
+end:
+    if (cursor)
+        krb5_kt_end_seq_get(kcontext, kt, &cursor);
+    if (kt)
+        krb5_kt_close(kcontext, kt);
+    krb5_free_context(kcontext);
+    
+    return result;
+}
+*/
+gss_client_response *authenticate_gss_client_init(const char* service, long int gss_flags, gss_client_state* state) {
+  OM_uint32 maj_stat;
+  OM_uint32 min_stat;
+  gss_buffer_desc name_token = GSS_C_EMPTY_BUFFER;
+  gss_client_response *response = NULL;
+  int ret = AUTH_GSS_COMPLETE;
+
+  state->server_name = GSS_C_NO_NAME;
+  state->context = GSS_C_NO_CONTEXT;
+  state->gss_flags = gss_flags;
+  state->username = NULL;
+  state->response = NULL;
+  
+  // Import server name first
+  name_token.length = strlen(service);
+  name_token.value = (char *)service;
+  
+  maj_stat = gss_import_name(&min_stat, &name_token, gss_krb5_nt_service_name, &state->server_name);
+  
+  if (GSS_ERROR(maj_stat)) {
+    response = gss_error(__func__, "gss_import_name", maj_stat, min_stat);
+    response->return_code = AUTH_GSS_ERROR;
+    goto end;
+  }
+  
+end:
+  if(response == NULL) {
+    response = calloc(1, sizeof(gss_client_response));
+    if(response == NULL) die1("Memory allocation failed");
+    response->return_code = ret;    
+  }
+
+  return response;
+}
+
+gss_client_response *authenticate_gss_client_clean(gss_client_state *state) {
+  OM_uint32 min_stat;
+  int ret = AUTH_GSS_COMPLETE;
+  gss_client_response *response = NULL;
+  
+  if(state->context != GSS_C_NO_CONTEXT)
+    gss_delete_sec_context(&min_stat, &state->context, GSS_C_NO_BUFFER);
+  
+  if(state->server_name != GSS_C_NO_NAME)
+    gss_release_name(&min_stat, &state->server_name);
+  
+  if(state->username != NULL) {
+    free(state->username);
+    state->username = NULL;
+  }
+
+  if (state->response != NULL) {
+    free(state->response);
+    state->response = NULL;
+  }
+  
+  if(response == NULL) {
+    response = calloc(1, sizeof(gss_client_response));
+    if(response == NULL) die1("Memory allocation failed");
+    response->return_code = ret;    
+  }
+
+  return response;
+}
+
+gss_client_response *authenticate_gss_client_step(gss_client_state* state, const char* challenge) {
+  OM_uint32 maj_stat;
+  OM_uint32 min_stat;
+  gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
+  gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
+  int ret = AUTH_GSS_CONTINUE;
+  gss_client_response *response = NULL;
+  
+  // Always clear out the old response
+  if (state->response != NULL) {
+    free(state->response);
+    state->response = NULL;
+  }
+  
+  // If there is a challenge (data from the server) we need to give it to GSS
+  if (challenge && *challenge) {
+    int len;
+    input_token.value = base64_decode(challenge, &len);
+    input_token.length = len;
+  }
+  
+  // Do GSSAPI step
+  maj_stat = gss_init_sec_context(&min_stat,
+                                  GSS_C_NO_CREDENTIAL,
+                                  &state->context,
+                                  state->server_name,
+                                  GSS_C_NO_OID,
+                                  (OM_uint32)state->gss_flags,
+                                  0,
+                                  GSS_C_NO_CHANNEL_BINDINGS,
+                                  &input_token,
+                                  NULL,
+                                  &output_token,
+                                  NULL,
+                                  NULL);
+
+  if ((maj_stat != GSS_S_COMPLETE) && (maj_stat != GSS_S_CONTINUE_NEEDED)) {
+    response = gss_error(__func__, "gss_init_sec_context", maj_stat, min_stat);
+    response->return_code = AUTH_GSS_ERROR;
+    goto end;
+  }
+  
+  ret = (maj_stat == GSS_S_COMPLETE) ? AUTH_GSS_COMPLETE : AUTH_GSS_CONTINUE;
+  // Grab the client response to send back to the server
+  if(output_token.length) {
+    state->response = base64_encode((const unsigned char *)output_token.value, output_token.length);
+    maj_stat = gss_release_buffer(&min_stat, &output_token);
+  }
+  
+  // Try to get the user name if we have completed all GSS operations
+  if (ret == AUTH_GSS_COMPLETE) {
+    gss_name_t gssuser = GSS_C_NO_NAME;
+    maj_stat = gss_inquire_context(&min_stat, state->context, &gssuser, NULL, NULL, NULL,  NULL, NULL, NULL);
+    
+    if(GSS_ERROR(maj_stat)) {
+      response = gss_error(__func__, "gss_inquire_context", maj_stat, min_stat);
+      response->return_code = AUTH_GSS_ERROR;
+      goto end;
+    }
+    
+    gss_buffer_desc name_token;
+    name_token.length = 0;
+    maj_stat = gss_display_name(&min_stat, gssuser, &name_token, NULL);
+    
+    if(GSS_ERROR(maj_stat)) {
+      if(name_token.value)
+        gss_release_buffer(&min_stat, &name_token);
+      gss_release_name(&min_stat, &gssuser);
+      
+      response = gss_error(__func__, "gss_display_name", maj_stat, min_stat);
+      response->return_code = AUTH_GSS_ERROR;
+      goto end;
+    } else {
+      state->username = (char *)malloc(name_token.length + 1);
+      if(state->username == NULL) die1("Memory allocation failed");
+      strncpy(state->username, (char*) name_token.value, name_token.length);
+      state->username[name_token.length] = 0;
+      gss_release_buffer(&min_stat, &name_token);
+      gss_release_name(&min_stat, &gssuser);
+    }
+  }
+
+end:
+  if(output_token.value)
+    gss_release_buffer(&min_stat, &output_token);
+  if(input_token.value)
+    free(input_token.value);
+
+  if(response == NULL) {
+    response = calloc(1, sizeof(gss_client_response));
+    if(response == NULL) die1("Memory allocation failed");
+    response->return_code = ret;
+  }
+
+  // Return the response
+  return response;
+}
+
+gss_client_response *authenticate_gss_client_unwrap(gss_client_state *state, const char *challenge) {
+  OM_uint32 maj_stat;
+  OM_uint32 min_stat;
+  gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
+  gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
+  gss_client_response *response = NULL;
+  int ret = AUTH_GSS_CONTINUE;
+    
+  // Always clear out the old response
+  if(state->response != NULL) {
+    free(state->response);
+    state->response = NULL;
+  }
+    
+  // If there is a challenge (data from the server) we need to give it to GSS
+  if(challenge && *challenge) {
+    int len;
+    input_token.value = base64_decode(challenge, &len);
+    input_token.length = len;
+  }
+    
+  // Do GSSAPI step
+  maj_stat = gss_unwrap(&min_stat,
+                          state->context,
+                          &input_token,
+                          &output_token,
+                          NULL,
+                          NULL);
+    
+  if(maj_stat != GSS_S_COMPLETE) {
+    response = gss_error(__func__, "gss_unwrap", maj_stat, min_stat);
+    response->return_code = AUTH_GSS_ERROR;
+    goto end;
+  } else {
+    ret = AUTH_GSS_COMPLETE;    
+  }
+    
+  // Grab the client response
+  if(output_token.length) {
+    state->response = base64_encode((const unsigned char *)output_token.value, output_token.length);
+    gss_release_buffer(&min_stat, &output_token);
+  }
+end:
+  if(output_token.value)
+    gss_release_buffer(&min_stat, &output_token);
+  if(input_token.value)
+    free(input_token.value);
+
+  if(response == NULL) {
+    response = calloc(1, sizeof(gss_client_response));
+    if(response == NULL) die1("Memory allocation failed");
+    response->return_code = ret;
+  }
+
+  // Return the response
+  return response;
+}
+
+gss_client_response *authenticate_gss_client_wrap(gss_client_state* state, const char* challenge, const char* user) {
+  OM_uint32 maj_stat;
+  OM_uint32 min_stat;
+  gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
+  gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
+  int ret = AUTH_GSS_CONTINUE;
+  gss_client_response *response = NULL;
+  char buf[4096], server_conf_flags;
+  unsigned long buf_size;
+    
+  // Always clear out the old response
+  if(state->response != NULL) {
+    free(state->response);
+    state->response = NULL;
+  }
+    
+  if(challenge && *challenge) {
+    int len;
+    input_token.value = base64_decode(challenge, &len);
+    input_token.length = len;
+  }
+    
+  if(user) {
+    // get bufsize
+    server_conf_flags = ((char*) input_token.value)[0];
+    ((char*) input_token.value)[0] = 0;
+    buf_size = ntohl(*((long *) input_token.value));
+    free(input_token.value);
+#ifdef PRINTFS
+    printf("User: %s, %c%c%c\n", user,
+               server_conf_flags & GSS_AUTH_P_NONE      ? 'N' : '-',
+               server_conf_flags & GSS_AUTH_P_INTEGRITY ? 'I' : '-',
+               server_conf_flags & GSS_AUTH_P_PRIVACY   ? 'P' : '-');
+    printf("Maximum GSS token size is %ld\n", buf_size);
+#endif
+        
+    // agree to terms (hack!)
+    buf_size = htonl(buf_size); // not relevant without integrity/privacy
+    memcpy(buf, &buf_size, 4);
+    buf[0] = GSS_AUTH_P_NONE;
+    // server decides if principal can log in as user
+    strncpy(buf + 4, user, sizeof(buf) - 4);
+    input_token.value = buf;
+    input_token.length = 4 + strlen(user);
+  }
+    
+  // Do GSSAPI wrap
+  maj_stat = gss_wrap(&min_stat,
+            state->context,
+            0,
+            GSS_C_QOP_DEFAULT,
+            &input_token,
+            NULL,
+            &output_token);
+    
+  if (maj_stat != GSS_S_COMPLETE) {
+    response = gss_error(__func__, "gss_wrap", maj_stat, min_stat);
+    response->return_code = AUTH_GSS_ERROR;
+    goto end;
+  } else
+    ret = AUTH_GSS_COMPLETE;
+  // Grab the client response to send back to the server
+  if (output_token.length) {
+    state->response = base64_encode((const unsigned char *)output_token.value, output_token.length);;
+    gss_release_buffer(&min_stat, &output_token);
+  }
+end:
+  if (output_token.value)
+    gss_release_buffer(&min_stat, &output_token);
+
+  if(response == NULL) {
+    response = calloc(1, sizeof(gss_client_response));
+    if(response == NULL) die1("Memory allocation failed");
+    response->return_code = ret;
+  }
+
+  // Return the response
+  return response;
+}
+
+gss_client_response *authenticate_gss_server_init(const char *service, bool constrained_delegation, const char *username, gss_server_state *state)
+{
+    OM_uint32 maj_stat;
+    OM_uint32 min_stat;
+    gss_buffer_desc name_token = GSS_C_EMPTY_BUFFER;
+    int ret = AUTH_GSS_COMPLETE;
+    gss_client_response *response = NULL;
+    gss_cred_usage_t usage = GSS_C_ACCEPT;
+
+    state->context = GSS_C_NO_CONTEXT;
+    state->server_name = GSS_C_NO_NAME;
+    state->client_name = GSS_C_NO_NAME;
+    state->server_creds = GSS_C_NO_CREDENTIAL;
+    state->client_creds = GSS_C_NO_CREDENTIAL;
+    state->username = NULL;
+    state->targetname = NULL;
+    state->response = NULL;
+    state->constrained_delegation = constrained_delegation;
+    state->delegated_credentials_cache = NULL;
+    
+    // Server name may be empty which means we aren't going to create our own creds
+    size_t service_len = strlen(service);
+    if (service_len != 0)
+    {
+        // Import server name first
+        name_token.length = strlen(service);
+        name_token.value = (char *)service;
+        
+        maj_stat = gss_import_name(&min_stat, &name_token, GSS_C_NT_HOSTBASED_SERVICE, &state->server_name);
+        
+        if (GSS_ERROR(maj_stat))
+        {
+            response = gss_error(__func__, "gss_import_name", maj_stat, min_stat);
+            response->return_code = AUTH_GSS_ERROR;
+            goto end;
+        }
+        
+        if (state->constrained_delegation)
+        {
+            usage = GSS_C_BOTH;
+        }
+
+        // Get credentials
+        maj_stat = gss_acquire_cred(&min_stat, state->server_name, GSS_C_INDEFINITE,
+                                    GSS_C_NO_OID_SET, usage, &state->server_creds, NULL, NULL);
+
+        if (GSS_ERROR(maj_stat))
+        {
+            response = gss_error(__func__, "gss_acquire_cred", maj_stat, min_stat);
+            response->return_code = AUTH_GSS_ERROR;
+            goto end;
+        }
+    }
+    
+    // If a username was passed, perform the S4U2Self protocol transition to acquire
+    // a credentials from that user as if we had done gss_accept_sec_context.
+    // In this scenario, the passed username is assumed to be already authenticated
+    // by some external mechanism, and we are here to "bootstrap" some gss credentials.
+    // In authenticate_gss_server_step we will bypass the actual authentication step.
+    if (username != NULL)
+    {
+	gss_name_t gss_username;
+
+	name_token.length = strlen(username);
+	name_token.value = (char *)username;
+
+	maj_stat = gss_import_name(&min_stat, &name_token, GSS_C_NT_USER_NAME, &gss_username);
+	if (GSS_ERROR(maj_stat))
+	{
+	    response = gss_error(__func__, "gss_import_name", maj_stat, min_stat);
+	    response->return_code = AUTH_GSS_ERROR;
+	    goto end;
+	}
+
+	maj_stat = gss_acquire_cred_impersonate_name(&min_stat,
+		state->server_creds,
+		gss_username,
+		GSS_C_INDEFINITE,
+		GSS_C_NO_OID_SET,
+		GSS_C_INITIATE,
+		&state->client_creds,
+		NULL,
+		NULL);
+
+	if (GSS_ERROR(maj_stat))
+	{
+	    response = gss_error(__func__, "gss_acquire_cred_impersonate_name", maj_stat, min_stat);
+	    response->return_code = AUTH_GSS_ERROR;
+	}
+
+	gss_release_name(&min_stat, &gss_username);
+
+	if (response != NULL)
+	{
+	    goto end;
+	}
+
+	// because the username MAY be a "local" username,
+	// we want get the canonical name from the acquired creds.
+	maj_stat = gss_inquire_cred(&min_stat, state->client_creds, &state->client_name, NULL, NULL, NULL);
+	if (GSS_ERROR(maj_stat))
+	{
+	    response = gss_error(__func__, "gss_inquire_cred", maj_stat, min_stat);
+	    response->return_code = AUTH_GSS_ERROR;
+	    goto end;
+	}
+    }
+
+end:
+    if(response == NULL) {
+      response = calloc(1, sizeof(gss_client_response));
+      if(response == NULL) die1("Memory allocation failed");
+      response->return_code = ret;
+    }
+
+    // Return the response
+    return response;
+}
+
+gss_client_response *authenticate_gss_server_clean(gss_server_state *state)
+{
+    OM_uint32 min_stat;
+    int ret = AUTH_GSS_COMPLETE;
+    gss_client_response *response = NULL;
+    
+    if (state->context != GSS_C_NO_CONTEXT)
+        gss_delete_sec_context(&min_stat, &state->context, GSS_C_NO_BUFFER);
+    if (state->server_name != GSS_C_NO_NAME)
+        gss_release_name(&min_stat, &state->server_name);
+    if (state->client_name != GSS_C_NO_NAME)
+        gss_release_name(&min_stat, &state->client_name);
+    if (state->server_creds != GSS_C_NO_CREDENTIAL)
+        gss_release_cred(&min_stat, &state->server_creds);
+    if (state->client_creds != GSS_C_NO_CREDENTIAL)
+        gss_release_cred(&min_stat, &state->client_creds);
+    if (state->username != NULL)
+    {
+        free(state->username);
+        state->username = NULL;
+    }
+    if (state->targetname != NULL)
+    {
+        free(state->targetname);
+        state->targetname = NULL;
+    }
+    if (state->response != NULL)
+    {
+        free(state->response);
+        state->response = NULL;
+    }
+    if (state->delegated_credentials_cache)
+    {
+	// TODO: what about actually destroying the cache? It can't be done now as
+	// the whole point is having it around for the lifetime of the "session"
+	free(state->delegated_credentials_cache);
+    }
+    
+    if(response == NULL) {
+      response = calloc(1, sizeof(gss_client_response));
+      if(response == NULL) die1("Memory allocation failed");
+      response->return_code = ret;
+    }
+
+    // Return the response
+    return response;
+}
+
+gss_client_response *authenticate_gss_server_step(gss_server_state *state, const char *auth_data)
+{
+    OM_uint32 maj_stat;
+    OM_uint32 min_stat;
+    gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
+    gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
+    int ret = AUTH_GSS_CONTINUE;
+    gss_client_response *response = NULL;
+    
+    // Always clear out the old response
+    if (state->response != NULL)
+    {
+        free(state->response);
+        state->response = NULL;
+    }
+    
+    // we don't need to check the authentication token if S4U2Self protocol
+    // transition was done, because we already have the client credentials.
+    if (state->client_creds == GSS_C_NO_CREDENTIAL)
+    {
+	if (auth_data && *auth_data)
+	{
+	    int len;
+	    input_token.value = base64_decode(auth_data, &len);
+	    input_token.length = len;
+	}
+	else
+	{
+	    response = calloc(1, sizeof(gss_client_response));
+	    if(response == NULL) die1("Memory allocation failed");
+	    response->message = strdup("No auth_data value in request from client");
+	    response->return_code = AUTH_GSS_ERROR;
+	    goto end;
+	}
+
+	maj_stat = gss_accept_sec_context(&min_stat,
+					  &state->context,
+					  state->server_creds,
+					  &input_token,
+					  GSS_C_NO_CHANNEL_BINDINGS,
+					  &state->client_name,
+					  NULL,
+					  &output_token,
+					  NULL,
+					  NULL,
+					  &state->client_creds);
+
+	if (GSS_ERROR(maj_stat))
+	{
+	    response = gss_error(__func__, "gss_accept_sec_context", maj_stat, min_stat);
+	    response->return_code = AUTH_GSS_ERROR;
+	    goto end;
+	}
+
+	// Grab the server response to send back to the client
+	if (output_token.length)
+	{
+	    state->response = base64_encode((const unsigned char *)output_token.value, output_token.length);
+	    maj_stat = gss_release_buffer(&min_stat, &output_token);
+	}
+    }
+
+    // Get the user name
+    maj_stat = gss_display_name(&min_stat, state->client_name, &output_token, NULL);
+    if (GSS_ERROR(maj_stat))
+    {
+	response = gss_error(__func__, "gss_display_name", maj_stat, min_stat);
+	response->return_code = AUTH_GSS_ERROR;
+	goto end;
+    }
+    state->username = (char *)malloc(output_token.length + 1);
+    strncpy(state->username, (char*) output_token.value, output_token.length);
+    state->username[output_token.length] = 0;
+
+    // Get the target name if no server creds were supplied
+    if (state->server_creds == GSS_C_NO_CREDENTIAL)
+    {
+	gss_name_t target_name = GSS_C_NO_NAME;
+	maj_stat = gss_inquire_context(&min_stat, state->context, NULL, &target_name, NULL, NULL, NULL, NULL, NULL);
+	if (GSS_ERROR(maj_stat))
+	{
+	    response = gss_error(__func__, "gss_inquire_context", maj_stat, min_stat);
+	    response->return_code = AUTH_GSS_ERROR;
+	    goto end;
+	}
+	maj_stat = gss_display_name(&min_stat, target_name, &output_token, NULL);
+	if (GSS_ERROR(maj_stat))
+	{
+	    response = gss_error(__func__, "gss_display_name", maj_stat, min_stat);
+	    response->return_code = AUTH_GSS_ERROR;
+	    goto end;
+	}
+	state->targetname = (char *)malloc(output_token.length + 1);
+	strncpy(state->targetname, (char*) output_token.value, output_token.length);
+	state->targetname[output_token.length] = 0;
+    }
+
+    if (state->constrained_delegation && state->client_creds != GSS_C_NO_CREDENTIAL)
+    {
+	if ((response = store_gss_creds(state)) != NULL)
+	{
+	    goto end;
+	}
+    }
+
+    ret = AUTH_GSS_COMPLETE;
+    
+end:
+    if (output_token.length)
+        gss_release_buffer(&min_stat, &output_token);
+    if (input_token.value)
+        free(input_token.value);
+
+    if(response == NULL) {
+      response = calloc(1, sizeof(gss_client_response));
+      if(response == NULL) die1("Memory allocation failed");
+      response->return_code = ret;
+    }
+
+    // Return the response
+    return response;
+}
+
+static gss_client_response *store_gss_creds(gss_server_state *state)
+{
+    OM_uint32 maj_stat, min_stat;
+    krb5_principal princ = NULL;
+    krb5_ccache ccache = NULL;
+    krb5_error_code problem;
+    krb5_context context;
+    gss_client_response *response = NULL;
+
+    problem = krb5_init_context(&context);
+    if (problem) {
+	response = other_error("No auth_data value in request from client");
+        return response;
+    }
+
+    problem = krb5_parse_name(context, state->username, &princ);
+    if (problem) {
+	response = krb5_ctx_error(context, problem);
+	goto end;
+    }
+
+    if ((response = create_krb5_ccache(state, context, princ, &ccache)))
+    {
+	goto end;
+    }
+
+    maj_stat = gss_krb5_copy_ccache(&min_stat, state->client_creds, ccache);
+    if (GSS_ERROR(maj_stat)) {
+        response = gss_error(__func__, "gss_krb5_copy_ccache", maj_stat, min_stat);
+        response->return_code = AUTH_GSS_ERROR;
+        goto end;
+    }
+
+    krb5_cc_close(context, ccache);
+    ccache = NULL;
+
+    response = calloc(1, sizeof(gss_client_response));
+    if(response == NULL) die1("Memory allocation failed");
+    // TODO: something other than AUTH_GSS_COMPLETE?
+    response->return_code = AUTH_GSS_COMPLETE;
+
+ end:
+    if (princ)
+	krb5_free_principal(context, princ);
+    if (ccache)
+	krb5_cc_destroy(context, ccache);
+    krb5_free_context(context);
+
+    return response;
+}
+
+static gss_client_response *create_krb5_ccache(gss_server_state *state, krb5_context kcontext, krb5_principal princ, krb5_ccache *ccache)
+{
+    char *ccname = NULL;
+    int fd;
+    krb5_error_code problem;
+    krb5_ccache tmp_ccache = NULL;
+    gss_client_response *error = NULL;
+
+    // TODO: mod_auth_kerb used a temp file under /run/httpd/krbcache. what can we do?
+    ccname = strdup("FILE:/tmp/krb5cc_nodekerberos_XXXXXX");
+    if (!ccname) die1("Memory allocation failed");
+
+    fd = mkstemp(ccname + strlen("FILE:"));
+    if (fd < 0) {
+	error = other_error("mkstemp() failed: %s", strerror(errno));
+	goto end;
+    }
+
+    close(fd);
+
+    problem = krb5_cc_resolve(kcontext, ccname, &tmp_ccache);
+    if (problem) {
+       error = krb5_ctx_error(kcontext, problem);
+       goto end;
+    }
+
+    problem = krb5_cc_initialize(kcontext, tmp_ccache, princ);
+    if (problem) {
+	error = krb5_ctx_error(kcontext, problem);
+	goto end;
+    }
+
+    state->delegated_credentials_cache = strdup(ccname);
+
+    // TODO: how/when to cleanup the creds cache file?
+    // TODO: how to expose the credentials expiration time?
+
+    *ccache = tmp_ccache;
+    tmp_ccache = NULL;
+
+ end:
+    if (tmp_ccache)
+	krb5_cc_destroy(kcontext, tmp_ccache);
+
+    if (ccname && error)
+	unlink(ccname);
+
+    if (ccname)
+	free(ccname);
+
+    return error;
+}
+
+
+gss_client_response *gss_error(const char *func, const char *op, OM_uint32 err_maj, OM_uint32 err_min) {
+  OM_uint32 maj_stat, min_stat;
+  OM_uint32 msg_ctx = 0;
+  gss_buffer_desc status_string;
+
+  gss_client_response *response = calloc(1, sizeof(gss_client_response));
+  if(response == NULL) die1("Memory allocation failed");
+  
+  char *message = NULL;
+  message = calloc(1024, 1);
+  if(message == NULL) die1("Memory allocation failed");
+
+  response->message = message;
+
+  int nleft = 1024;
+  int n;
+
+  n = snprintf(message, nleft, "%s(%s)", func, op);
+  message += n;
+  nleft -= n;
+
+  do {
+    maj_stat = gss_display_status (&min_stat,
+                                   err_maj,
+                                   GSS_C_GSS_CODE,
+                                   GSS_C_NO_OID,
+                                   &msg_ctx,
+                                   &status_string);
+    if(GSS_ERROR(maj_stat))
+      break;
+    
+    n = snprintf(message, nleft, ": %.*s",
+	    (int)status_string.length, (char*)status_string.value);
+    message += n;
+    nleft -= n;
+
+    gss_release_buffer(&min_stat, &status_string);
+    
+    maj_stat = gss_display_status (&min_stat,
+                                   err_min,
+                                   GSS_C_MECH_CODE,
+                                   GSS_C_NULL_OID,
+                                   &msg_ctx,
+                                   &status_string);
+    if(!GSS_ERROR(maj_stat)) {
+	n = snprintf(message, nleft, ": %.*s",
+		(int)status_string.length, (char*)status_string.value);
+	message += n;
+	nleft -= n;
+
+      gss_release_buffer(&min_stat, &status_string);
+    }
+  } while (!GSS_ERROR(maj_stat) && msg_ctx != 0);
+
+  return response;
+}
+
+static gss_client_response *krb5_ctx_error(krb5_context context, krb5_error_code problem)
+{
+    gss_client_response *response = NULL;
+    const char *error_text = krb5_get_error_message(context, problem);
+    response = calloc(1, sizeof(gss_client_response));
+    if(response == NULL) die1("Memory allocation failed");
+    response->message = strdup(error_text);
+    // TODO: something other than AUTH_GSS_ERROR? AUTH_KRB5_ERROR ?
+    response->return_code = AUTH_GSS_ERROR;
+    krb5_free_error_message(context, error_text);
+    return response;
+}
+
+static gss_client_response *other_error(const char *fmt, ...)
+{
+    size_t needed;
+    char *msg;
+    gss_client_response *response = NULL;
+    va_list ap, aps;
+
+    va_start(ap, fmt);
+
+    va_copy(aps, ap);
+    needed = snprintf(NULL, 0, fmt, aps);
+    va_end(aps);
+
+    msg = malloc(needed);
+    if (!msg) die1("Memory allocation failed");
+
+    vsnprintf(msg, needed, fmt, ap);
+    va_end(ap);
+
+    response = calloc(1, sizeof(gss_client_response));
+    if(response == NULL) die1("Memory allocation failed");
+    response->message = msg;
+
+    // TODO: something other than AUTH_GSS_ERROR?
+    response->return_code = AUTH_GSS_ERROR;
+
+    return response;
+}
+
+
+#pragma clang diagnostic pop
+

http://git-wip-us.apache.org/repos/asf/couchdb-nmo/blob/753f1767/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/kerberosgss.h
----------------------------------------------------------------------
diff --git a/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/kerberosgss.h b/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/kerberosgss.h
new file mode 100644
index 0000000..fa7e311
--- /dev/null
+++ b/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/kerberosgss.h
@@ -0,0 +1,73 @@
+/**
+ * Copyright (c) 2006-2009 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **/
+#ifndef KERBEROS_GSS_H
+#define KERBEROS_GSS_H
+
+#include <stdbool.h>
+
+#include <gssapi/gssapi.h>
+#include <gssapi/gssapi_generic.h>
+#include <gssapi/gssapi_krb5.h>
+
+#define krb5_get_err_text(context,code) error_message(code)
+
+#define AUTH_GSS_ERROR      -1
+#define AUTH_GSS_COMPLETE    1
+#define AUTH_GSS_CONTINUE    0
+
+#define GSS_AUTH_P_NONE         1
+#define GSS_AUTH_P_INTEGRITY    2
+#define GSS_AUTH_P_PRIVACY      4
+
+typedef struct {
+  int return_code;
+  char *message;
+} gss_client_response;
+
+typedef struct {
+  gss_ctx_id_t     context;
+  gss_name_t       server_name;
+  long int         gss_flags;
+  char*            username;
+  char*            response;
+} gss_client_state;
+
+typedef struct {
+  gss_ctx_id_t     context;
+  gss_name_t       server_name;
+  gss_name_t       client_name;
+  gss_cred_id_t    server_creds;
+  gss_cred_id_t    client_creds;
+  char*            username;
+  char*            targetname;
+  char*            response;
+  bool		   constrained_delegation;
+  char*		   delegated_credentials_cache;
+} gss_server_state;
+
+// char* server_principal_details(const char* service, const char* hostname);
+
+gss_client_response *authenticate_gss_client_init(const char* service, long int gss_flags, gss_client_state* state);
+gss_client_response *authenticate_gss_client_clean(gss_client_state *state);
+gss_client_response *authenticate_gss_client_step(gss_client_state *state, const char *challenge);
+gss_client_response *authenticate_gss_client_unwrap(gss_client_state* state, const char* challenge);
+gss_client_response *authenticate_gss_client_wrap(gss_client_state* state, const char* challenge, const char* user);
+
+gss_client_response *authenticate_gss_server_init(const char* service, bool constrained_delegation, const char *username, gss_server_state* state);
+gss_client_response *authenticate_gss_server_clean(gss_server_state *state);
+gss_client_response *authenticate_gss_server_step(gss_server_state *state, const char *challenge);
+
+#endif

http://git-wip-us.apache.org/repos/asf/couchdb-nmo/blob/753f1767/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/sspi.js
----------------------------------------------------------------------
diff --git a/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/sspi.js b/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/sspi.js
new file mode 100644
index 0000000..d9120fb
--- /dev/null
+++ b/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/sspi.js
@@ -0,0 +1,15 @@
+// Load the native SSPI classes
+var kerberos = require('../build/Release/kerberos')
+  , Kerberos = kerberos.Kerberos
+  , SecurityBuffer = require('./win32/wrappers/security_buffer').SecurityBuffer
+  , SecurityBufferDescriptor = require('./win32/wrappers/security_buffer_descriptor').SecurityBufferDescriptor
+  , SecurityCredentials = require('./win32/wrappers/security_credentials').SecurityCredentials
+  , SecurityContext = require('./win32/wrappers/security_context').SecurityContext;
+var SSPI = function() {
+}
+
+exports.SSPI = SSPI;
+exports.SecurityBuffer = SecurityBuffer;
+exports.SecurityBufferDescriptor = SecurityBufferDescriptor;
+exports.SecurityCredentials = SecurityCredentials;
+exports.SecurityContext = SecurityContext;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/couchdb-nmo/blob/753f1767/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/base64.c
----------------------------------------------------------------------
diff --git a/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/base64.c b/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/base64.c
new file mode 100644
index 0000000..502a021
--- /dev/null
+++ b/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/base64.c
@@ -0,0 +1,121 @@
+/**
+ * Copyright (c) 2006-2008 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **/
+
+#include "base64.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+// base64 tables
+static char basis_64[] =
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+static signed char index_64[128] =
+{
+    -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
+    -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
+    -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,
+    52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1,
+    -1, 0, 1, 2,  3, 4, 5, 6,  7, 8, 9,10, 11,12,13,14,
+    15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1,
+    -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
+    41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1
+};
+#define CHAR64(c)  (((c) < 0 || (c) > 127) ? -1 : index_64[(c)])
+
+// base64_encode    :    base64 encode
+//
+// value            :    data to encode
+// vlen             :    length of data
+// (result)         :    new char[] - c-str of result
+char *base64_encode(const unsigned char *value, int vlen)
+{
+    char *result = (char *)malloc((vlen * 4) / 3 + 5);
+    char *out = result;
+    unsigned char oval;
+
+    while (vlen >= 3)
+    {
+        *out++ = basis_64[value[0] >> 2];
+        *out++ = basis_64[((value[0] << 4) & 0x30) | (value[1] >> 4)];
+        *out++ = basis_64[((value[1] << 2) & 0x3C) | (value[2] >> 6)];
+        *out++ = basis_64[value[2] & 0x3F];
+        value += 3;
+        vlen -= 3;
+    }
+    if (vlen > 0)
+    {
+        *out++ = basis_64[value[0] >> 2];
+        oval = (value[0] << 4) & 0x30;
+        if (vlen > 1) oval |= value[1] >> 4;
+        *out++ = basis_64[oval];
+        *out++ = (vlen < 2) ? '=' : basis_64[(value[1] << 2) & 0x3C];
+        *out++ = '=';
+    }
+    *out = '\0';
+
+    return result;
+}
+
+// base64_decode    :    base64 decode
+//
+// value            :    c-str to decode
+// rlen             :    length of decoded result
+// (result)         :    new unsigned char[] - decoded result
+unsigned char *base64_decode(const char *value, int *rlen)
+{
+    int c1, c2, c3, c4;
+    int vlen = (int)strlen(value);
+    unsigned char *result =(unsigned char *)malloc((vlen * 3) / 4 + 1);
+    unsigned char *out = result;
+    *rlen = 0;
+
+    while (1)
+    {
+        if (value[0]==0)
+            return result;
+        c1 = value[0];
+        if (CHAR64(c1) == -1)
+            goto base64_decode_error;;
+        c2 = value[1];
+        if (CHAR64(c2) == -1)
+            goto base64_decode_error;;
+        c3 = value[2];
+        if ((c3 != '=') && (CHAR64(c3) == -1))
+            goto base64_decode_error;;
+        c4 = value[3];
+        if ((c4 != '=') && (CHAR64(c4) == -1))
+            goto base64_decode_error;;
+
+        value += 4;
+        *out++ = (CHAR64(c1) << 2) | (CHAR64(c2) >> 4);
+        *rlen += 1;
+        if (c3 != '=')
+        {
+            *out++ = ((CHAR64(c2) << 4) & 0xf0) | (CHAR64(c3) >> 2);
+            *rlen += 1;
+            if (c4 != '=')
+            {
+                *out++ = ((CHAR64(c3) << 6) & 0xc0) | CHAR64(c4);
+                *rlen += 1;
+            }
+        }
+    }
+
+base64_decode_error:
+    *result = 0;
+    *rlen = 0;
+    return result;
+}

http://git-wip-us.apache.org/repos/asf/couchdb-nmo/blob/753f1767/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/base64.h
----------------------------------------------------------------------
diff --git a/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/base64.h b/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/base64.h
new file mode 100644
index 0000000..f0e1f06
--- /dev/null
+++ b/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/base64.h
@@ -0,0 +1,18 @@
+/**
+ * Copyright (c) 2006-2008 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **/
+
+char *base64_encode(const unsigned char *value, int vlen);
+unsigned char *base64_decode(const char *value, int *rlen);

http://git-wip-us.apache.org/repos/asf/couchdb-nmo/blob/753f1767/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/kerberos.cc
----------------------------------------------------------------------
diff --git a/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/kerberos.cc b/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/kerberos.cc
new file mode 100644
index 0000000..c7b583f
--- /dev/null
+++ b/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/kerberos.cc
@@ -0,0 +1,51 @@
+#include "kerberos.h"
+#include <stdlib.h>
+#include <tchar.h>
+#include "base64.h"
+#include "wrappers/security_buffer.h"
+#include "wrappers/security_buffer_descriptor.h"
+#include "wrappers/security_context.h"
+#include "wrappers/security_credentials.h"
+
+Nan::Persistent<FunctionTemplate> Kerberos::constructor_template;
+
+Kerberos::Kerberos() : Nan::ObjectWrap() {
+}
+
+void Kerberos::Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target) {
+  // Grab the scope of the call from Node
+  Nan::HandleScope scope;
+
+  // Define a new function template
+  Local<FunctionTemplate> t = Nan::New<FunctionTemplate>(New);
+  t->InstanceTemplate()->SetInternalFieldCount(1);
+  t->SetClassName(Nan::New<String>("Kerberos").ToLocalChecked());
+
+  // Set persistent
+  constructor_template.Reset(t);
+
+  // Set the symbol
+  Nan::Set(target, Nan::New<String>("Kerberos").ToLocalChecked(), t->GetFunction());
+}
+
+NAN_METHOD(Kerberos::New) {
+  // Load the security.dll library
+  load_library();
+  // Create a Kerberos instance
+  Kerberos *kerberos = new Kerberos();
+  // Return the kerberos object
+  kerberos->Wrap(info.This());
+  // Return the object
+  info.GetReturnValue().Set(info.This());
+}
+
+// Exporting function
+NAN_MODULE_INIT(init) {
+  Kerberos::Initialize(target);
+  SecurityContext::Initialize(target);
+  SecurityBuffer::Initialize(target);
+  SecurityBufferDescriptor::Initialize(target);
+  SecurityCredentials::Initialize(target);
+}
+
+NODE_MODULE(kerberos, init);

http://git-wip-us.apache.org/repos/asf/couchdb-nmo/blob/753f1767/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/kerberos.h
----------------------------------------------------------------------
diff --git a/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/kerberos.h b/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/kerberos.h
new file mode 100644
index 0000000..0fd2760
--- /dev/null
+++ b/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/kerberos.h
@@ -0,0 +1,60 @@
+#ifndef KERBEROS_H
+#define KERBEROS_H
+
+#include <node.h>
+#include <node_object_wrap.h>
+#include <v8.h>
+#include "nan.h"
+
+extern "C" {
+  #include "kerberos_sspi.h"
+  #include "base64.h"
+}
+
+using namespace v8;
+using namespace node;
+
+class Kerberos : public Nan::ObjectWrap {
+
+public:
+  Kerberos();
+  ~Kerberos() {};
+
+  // Constructor used for creating new Kerberos objects from C++
+  static Nan::Persistent<FunctionTemplate> constructor_template;
+
+  // Initialize function for the object
+  static void Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target);
+
+  // Method available
+  static NAN_METHOD(AcquireAlternateCredentials);
+  static NAN_METHOD(PrepareOutboundPackage);
+  static NAN_METHOD(DecryptMessage);
+  static NAN_METHOD(EncryptMessage);
+  static NAN_METHOD(QueryContextAttributes);
+
+private:
+  static NAN_METHOD(New);
+
+  // Pointer to context object
+  SEC_WINNT_AUTH_IDENTITY m_Identity;
+  // credentials
+  CredHandle m_Credentials;
+  // Expiry time for ticket
+  TimeStamp Expiration;
+  // package info
+  SecPkgInfo m_PkgInfo;
+  // context
+  CtxtHandle m_Context;
+  // Do we have a context
+  bool m_HaveContext;
+  // Attributes
+  DWORD CtxtAttr;
+
+  // Handles the uv calls
+  static void Process(uv_work_t* work_req);
+  // Called after work is done
+  static void After(uv_work_t* work_req);
+};
+
+#endif
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/couchdb-nmo/blob/753f1767/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/kerberos_sspi.c
----------------------------------------------------------------------
diff --git a/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/kerberos_sspi.c b/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/kerberos_sspi.c
new file mode 100644
index 0000000..d75c9ab
--- /dev/null
+++ b/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/kerberos_sspi.c
@@ -0,0 +1,244 @@
+#include "kerberos_sspi.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+static HINSTANCE _sspi_security_dll = NULL; 
+static HINSTANCE _sspi_secur32_dll = NULL;
+
+/**
+ * Encrypt A Message
+ */
+SECURITY_STATUS SEC_ENTRY _sspi_EncryptMessage(PCtxtHandle phContext, unsigned long fQOP, PSecBufferDesc pMessage, unsigned long MessageSeqNo) {
+  // Create function pointer instance
+  encryptMessage_fn pfn_encryptMessage = NULL;
+
+  // Return error if library not loaded
+  if(_sspi_security_dll == NULL) return -1;
+
+  // Map function to library method
+  pfn_encryptMessage = (encryptMessage_fn)GetProcAddress(_sspi_security_dll, "EncryptMessage");
+  // Check if the we managed to map function pointer
+  if(!pfn_encryptMessage) {
+    printf("GetProcAddress failed.\n");
+    return -2;
+  }
+
+  // Call the function
+  return (*pfn_encryptMessage)(phContext, fQOP, pMessage, MessageSeqNo);
+}
+
+/**
+ * Acquire Credentials
+ */
+SECURITY_STATUS SEC_ENTRY _sspi_AcquireCredentialsHandle(
+  LPSTR pszPrincipal, LPSTR pszPackage, unsigned long fCredentialUse,
+  void * pvLogonId, void * pAuthData, SEC_GET_KEY_FN pGetKeyFn, void * pvGetKeyArgument,
+  PCredHandle phCredential, PTimeStamp ptsExpiry
+) {
+  SECURITY_STATUS     status;
+  // Create function pointer instance
+  acquireCredentialsHandle_fn pfn_acquireCredentialsHandle = NULL;
+
+  // Return error if library not loaded
+  if(_sspi_security_dll == NULL) return -1;
+
+  // Map function
+  #ifdef _UNICODE
+      pfn_acquireCredentialsHandle = (acquireCredentialsHandle_fn)GetProcAddress(_sspi_security_dll, "AcquireCredentialsHandleW");
+  #else
+      pfn_acquireCredentialsHandle = (acquireCredentialsHandle_fn)GetProcAddress(_sspi_security_dll, "AcquireCredentialsHandleA");
+  #endif
+
+  // Check if the we managed to map function pointer
+  if(!pfn_acquireCredentialsHandle) {
+    printf("GetProcAddress failed.\n");
+    return -2;
+  }
+
+  // Status
+  status = (*pfn_acquireCredentialsHandle)(pszPrincipal, pszPackage, fCredentialUse,
+      pvLogonId, pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential, ptsExpiry
+    );
+
+  // Call the function
+  return status;
+}
+
+/**
+ * Delete Security Context
+ */
+SECURITY_STATUS SEC_ENTRY _sspi_DeleteSecurityContext(PCtxtHandle phContext) {
+  // Create function pointer instance
+  deleteSecurityContext_fn pfn_deleteSecurityContext = NULL;
+
+  // Return error if library not loaded
+  if(_sspi_security_dll == NULL) return -1;
+  // Map function
+  pfn_deleteSecurityContext = (deleteSecurityContext_fn)GetProcAddress(_sspi_security_dll, "DeleteSecurityContext");
+
+  // Check if the we managed to map function pointer
+  if(!pfn_deleteSecurityContext) {
+    printf("GetProcAddress failed.\n");
+    return -2;
+  }
+
+  // Call the function
+  return (*pfn_deleteSecurityContext)(phContext);
+}
+
+/**
+ * Decrypt Message
+ */
+SECURITY_STATUS SEC_ENTRY _sspi_DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage, unsigned long MessageSeqNo, unsigned long pfQOP) {
+  // Create function pointer instance
+  decryptMessage_fn pfn_decryptMessage = NULL;
+
+  // Return error if library not loaded
+  if(_sspi_security_dll == NULL) return -1;
+  // Map function
+  pfn_decryptMessage = (decryptMessage_fn)GetProcAddress(_sspi_security_dll, "DecryptMessage");
+
+  // Check if the we managed to map function pointer
+  if(!pfn_decryptMessage) {
+    printf("GetProcAddress failed.\n");
+    return -2;
+  }
+
+  // Call the function
+  return (*pfn_decryptMessage)(phContext, pMessage, MessageSeqNo, pfQOP);
+}
+
+/**
+ * Initialize Security Context
+ */
+SECURITY_STATUS SEC_ENTRY _sspi_initializeSecurityContext(
+  PCredHandle phCredential, PCtxtHandle phContext,
+  LPSTR pszTargetName, unsigned long fContextReq, 
+  unsigned long Reserved1, unsigned long TargetDataRep, 
+  PSecBufferDesc pInput, unsigned long Reserved2,
+  PCtxtHandle phNewContext, PSecBufferDesc pOutput,
+  unsigned long * pfContextAttr, PTimeStamp ptsExpiry
+) {
+  SECURITY_STATUS status;
+  // Create function pointer instance
+  initializeSecurityContext_fn pfn_initializeSecurityContext = NULL;
+
+  // Return error if library not loaded
+  if(_sspi_security_dll == NULL) return -1;
+  
+  // Map function
+  #ifdef _UNICODE
+    pfn_initializeSecurityContext = (initializeSecurityContext_fn)GetProcAddress(_sspi_security_dll, "InitializeSecurityContextW");
+  #else
+    pfn_initializeSecurityContext = (initializeSecurityContext_fn)GetProcAddress(_sspi_security_dll, "InitializeSecurityContextA");
+  #endif
+
+  // Check if the we managed to map function pointer
+  if(!pfn_initializeSecurityContext) {
+    printf("GetProcAddress failed.\n");
+    return -2;
+  }
+
+  // Execute intialize context
+  status = (*pfn_initializeSecurityContext)(
+    phCredential, phContext, pszTargetName, fContextReq, 
+    Reserved1, TargetDataRep, pInput, Reserved2,
+    phNewContext, pOutput, pfContextAttr, ptsExpiry
+  );
+
+  // Call the function
+  return status;
+}
+/**
+ * Query Context Attributes
+ */
+SECURITY_STATUS SEC_ENTRY _sspi_QueryContextAttributes(
+  PCtxtHandle phContext, unsigned long ulAttribute, void * pBuffer
+) {
+  // Create function pointer instance
+  queryContextAttributes_fn pfn_queryContextAttributes = NULL;
+
+  // Return error if library not loaded
+  if(_sspi_security_dll == NULL) return -1;
+
+  #ifdef _UNICODE
+    pfn_queryContextAttributes = (queryContextAttributes_fn)GetProcAddress(_sspi_security_dll, "QueryContextAttributesW");
+  #else
+    pfn_queryContextAttributes = (queryContextAttributes_fn)GetProcAddress(_sspi_security_dll, "QueryContextAttributesA");
+  #endif
+
+  // Check if the we managed to map function pointer
+  if(!pfn_queryContextAttributes) {
+    printf("GetProcAddress failed.\n");
+    return -2;
+  }
+
+  // Call the function
+  return (*pfn_queryContextAttributes)(
+    phContext, ulAttribute, pBuffer
+  );
+}
+
+/**
+ * InitSecurityInterface
+ */
+PSecurityFunctionTable _ssip_InitSecurityInterface() {
+  INIT_SECURITY_INTERFACE InitSecurityInterface;
+  PSecurityFunctionTable pSecurityInterface = NULL;
+
+  // Return error if library not loaded
+  if(_sspi_security_dll == NULL) return NULL;
+
+  #ifdef _UNICODE
+    // Get the address of the InitSecurityInterface function.
+    InitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress (
+                                          _sspi_secur32_dll, 
+                                          TEXT("InitSecurityInterfaceW"));
+  #else
+    // Get the address of the InitSecurityInterface function.
+    InitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress (
+                                          _sspi_secur32_dll, 
+                                          TEXT("InitSecurityInterfaceA"));
+  #endif
+
+  if(!InitSecurityInterface) {
+    printf (TEXT("Failed in getting the function address, Error: %x"), GetLastError ());
+    return NULL;
+  }
+
+  // Use InitSecurityInterface to get the function table.
+  pSecurityInterface = (*InitSecurityInterface)();
+
+  if(!pSecurityInterface) {
+    printf (TEXT("Failed in getting the function table, Error: %x"), GetLastError ());
+    return NULL;
+  }
+
+  return pSecurityInterface;
+}
+
+/**
+ * Load security.dll dynamically
+ */
+int load_library() {
+  DWORD err;
+  // Load the library
+  _sspi_security_dll = LoadLibrary("security.dll");
+
+  // Check if the library loaded
+  if(_sspi_security_dll == NULL) {
+    err = GetLastError();
+    return err;
+  }
+
+  // Load the library
+  _sspi_secur32_dll = LoadLibrary("secur32.dll");
+
+  // Check if the library loaded
+  if(_sspi_secur32_dll == NULL) {
+    err = GetLastError();
+    return err;
+  }
+
+  return 0;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/couchdb-nmo/blob/753f1767/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/kerberos_sspi.h
----------------------------------------------------------------------
diff --git a/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/kerberos_sspi.h b/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/kerberos_sspi.h
new file mode 100644
index 0000000..a3008dc
--- /dev/null
+++ b/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/kerberos_sspi.h
@@ -0,0 +1,106 @@
+#ifndef SSPI_C_H
+#define SSPI_C_H
+
+#define SECURITY_WIN32 1
+
+#include <windows.h>
+#include <sspi.h>
+
+/**
+ * Encrypt A Message
+ */
+SECURITY_STATUS SEC_ENTRY _sspi_EncryptMessage(PCtxtHandle phContext, unsigned long fQOP, PSecBufferDesc pMessage, unsigned long MessageSeqNo);
+
+typedef DWORD (WINAPI *encryptMessage_fn)(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo);  
+
+/**
+ * Acquire Credentials
+ */
+SECURITY_STATUS SEC_ENTRY _sspi_AcquireCredentialsHandle(
+  LPSTR pszPrincipal,                 // Name of principal
+  LPSTR pszPackage,                   // Name of package
+  unsigned long fCredentialUse,       // Flags indicating use
+  void * pvLogonId,                   // Pointer to logon ID
+  void * pAuthData,                   // Package specific data
+  SEC_GET_KEY_FN pGetKeyFn,           // Pointer to GetKey() func
+  void * pvGetKeyArgument,            // Value to pass to GetKey()
+  PCredHandle phCredential,           // (out) Cred Handle
+  PTimeStamp ptsExpiry                // (out) Lifetime (optional)
+);
+
+typedef DWORD (WINAPI *acquireCredentialsHandle_fn)(
+    LPSTR pszPrincipal, LPSTR pszPackage, unsigned long fCredentialUse,
+    void * pvLogonId, void * pAuthData, SEC_GET_KEY_FN pGetKeyFn, void * pvGetKeyArgument,
+    PCredHandle phCredential, PTimeStamp ptsExpiry
+  );
+
+/**
+ * Delete Security Context
+ */
+SECURITY_STATUS SEC_ENTRY _sspi_DeleteSecurityContext(
+  PCtxtHandle phContext               // Context to delete
+);
+
+typedef DWORD (WINAPI *deleteSecurityContext_fn)(PCtxtHandle phContext);  
+
+/**
+ * Decrypt Message
+ */
+SECURITY_STATUS SEC_ENTRY _sspi_DecryptMessage(
+  PCtxtHandle phContext, 
+  PSecBufferDesc pMessage, 
+  unsigned long MessageSeqNo, 
+  unsigned long pfQOP
+);
+
+typedef DWORD (WINAPI *decryptMessage_fn)(
+  PCtxtHandle phContext, PSecBufferDesc pMessage, unsigned long MessageSeqNo, unsigned long pfQOP);
+
+/**
+ * Initialize Security Context
+ */
+SECURITY_STATUS SEC_ENTRY _sspi_initializeSecurityContext(
+  PCredHandle phCredential,       // Cred to base context
+  PCtxtHandle phContext,          // Existing context (OPT)
+  LPSTR pszTargetName,            // Name of target
+  unsigned long fContextReq,      // Context Requirements
+  unsigned long Reserved1,        // Reserved, MBZ
+  unsigned long TargetDataRep,    // Data rep of target
+  PSecBufferDesc pInput,          // Input Buffers
+  unsigned long Reserved2,        // Reserved, MBZ
+  PCtxtHandle phNewContext,       // (out) New Context handle
+  PSecBufferDesc pOutput,         // (inout) Output Buffers
+  unsigned long * pfContextAttr,  // (out) Context attrs
+  PTimeStamp ptsExpiry            // (out) Life span (OPT)
+);
+
+typedef DWORD (WINAPI *initializeSecurityContext_fn)(
+  PCredHandle phCredential, PCtxtHandle phContext, LPSTR pszTargetName, unsigned long fContextReq, 
+  unsigned long Reserved1, unsigned long TargetDataRep, PSecBufferDesc pInput, unsigned long Reserved2,
+  PCtxtHandle phNewContext, PSecBufferDesc pOutput, unsigned long * pfContextAttr, PTimeStamp ptsExpiry);
+
+/**
+ * Query Context Attributes
+ */
+SECURITY_STATUS SEC_ENTRY _sspi_QueryContextAttributes(
+  PCtxtHandle phContext,          // Context to query
+  unsigned long ulAttribute,      // Attribute to query
+  void * pBuffer                  // Buffer for attributes
+);
+
+typedef DWORD (WINAPI *queryContextAttributes_fn)(
+  PCtxtHandle phContext, unsigned long ulAttribute, void * pBuffer);
+
+/**
+ * InitSecurityInterface
+ */
+PSecurityFunctionTable _ssip_InitSecurityInterface();
+
+typedef DWORD (WINAPI *initSecurityInterface_fn) ();
+
+/**
+ * Load security.dll dynamically
+ */
+int load_library();
+
+#endif
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/couchdb-nmo/blob/753f1767/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/worker.cc
----------------------------------------------------------------------
diff --git a/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/worker.cc b/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/worker.cc
new file mode 100644
index 0000000..e7a472f
--- /dev/null
+++ b/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/worker.cc
@@ -0,0 +1,7 @@
+#include "worker.h"
+
+Worker::Worker() {
+}
+
+Worker::~Worker() {  
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/couchdb-nmo/blob/753f1767/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/worker.h
----------------------------------------------------------------------
diff --git a/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/worker.h b/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/worker.h
new file mode 100644
index 0000000..c2ccb6b
--- /dev/null
+++ b/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/worker.h
@@ -0,0 +1,38 @@
+#ifndef WORKER_H_
+#define WORKER_H_
+
+#include <node.h>
+#include <node_object_wrap.h>
+#include <v8.h>
+#include <nan.h>
+
+using namespace node;
+using namespace v8;
+
+class Worker {
+  public:
+    Worker();
+    virtual ~Worker();
+
+    // libuv's request struct.
+    uv_work_t request;
+    // Callback
+    Nan::Callback *callback;
+    // Parameters
+    void *parameters;
+    // Results
+    void *return_value;
+    // Did we raise an error
+    bool error;
+    // The error message
+    char *error_message;
+    // Error code if not message
+    int error_code;
+    // Any return code
+    int return_code;
+    // Method we are going to fire
+    void (*execute)(Worker *worker);
+    Local<Value> (*mapper)(Worker *worker);
+};
+
+#endif  // WORKER_H_

http://git-wip-us.apache.org/repos/asf/couchdb-nmo/blob/753f1767/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/wrappers/security_buffer.cc
----------------------------------------------------------------------
diff --git a/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/wrappers/security_buffer.cc b/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/wrappers/security_buffer.cc
new file mode 100644
index 0000000..fdf8e49
--- /dev/null
+++ b/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/wrappers/security_buffer.cc
@@ -0,0 +1,101 @@
+#include <node.h>
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <v8.h>
+#include <node_buffer.h>
+#include <cstring>
+#include <cmath>
+#include <cstdlib>
+#include <iostream>
+#include <limits>
+
+#include "security_buffer.h"
+
+using namespace node;
+
+Nan::Persistent<FunctionTemplate> SecurityBuffer::constructor_template;
+
+SecurityBuffer::SecurityBuffer(uint32_t security_type, size_t size) : Nan::ObjectWrap() {
+  this->size = size;
+  this->data = calloc(size, sizeof(char));
+  this->security_type = security_type;
+  // Set up the data in the sec_buffer
+  this->sec_buffer.BufferType = security_type;
+  this->sec_buffer.cbBuffer = (unsigned long)size;
+  this->sec_buffer.pvBuffer = this->data;
+}
+
+SecurityBuffer::SecurityBuffer(uint32_t security_type, size_t size, void *data) : Nan::ObjectWrap() {
+  this->size = size;
+  this->data = data;
+  this->security_type = security_type;
+  // Set up the data in the sec_buffer
+  this->sec_buffer.BufferType = security_type;
+  this->sec_buffer.cbBuffer = (unsigned long)size;
+  this->sec_buffer.pvBuffer = this->data;
+}
+
+SecurityBuffer::~SecurityBuffer() {
+  free(this->data);
+}
+
+NAN_METHOD(SecurityBuffer::New) {
+  SecurityBuffer *security_obj;
+
+  if(info.Length() != 2)
+    return Nan::ThrowError("Two parameters needed integer buffer type and  [32 bit integer/Buffer] required");
+
+  if(!info[0]->IsInt32())
+    return Nan::ThrowError("Two parameters needed integer buffer type and  [32 bit integer/Buffer] required");
+
+  if(!info[1]->IsInt32() && !Buffer::HasInstance(info[1]))
+    return Nan::ThrowError("Two parameters needed integer buffer type and  [32 bit integer/Buffer] required");
+
+  // Unpack buffer type
+  uint32_t buffer_type = info[0]->ToUint32()->Value();
+
+  // If we have an integer
+  if(info[1]->IsInt32()) {
+    security_obj = new SecurityBuffer(buffer_type, info[1]->ToUint32()->Value());
+  } else {
+    // Get the length of the Buffer
+    size_t length = Buffer::Length(info[1]->ToObject());
+    // Allocate space for the internal void data pointer
+    void *data = calloc(length, sizeof(char));
+    // Write the data to out of V8 heap space
+    memcpy(data, Buffer::Data(info[1]->ToObject()), length);
+    // Create new SecurityBuffer
+    security_obj = new SecurityBuffer(buffer_type, length, data);
+  }
+
+  // Wrap it
+  security_obj->Wrap(info.This());
+  // Return the object
+  info.GetReturnValue().Set(info.This());
+}
+
+NAN_METHOD(SecurityBuffer::ToBuffer) {
+  // Unpack the Security Buffer object
+  SecurityBuffer *security_obj = Nan::ObjectWrap::Unwrap<SecurityBuffer>(info.This());
+  // Create a Buffer
+  Local<Object> buffer = Nan::CopyBuffer((char *)security_obj->data, (uint32_t)security_obj->size).ToLocalChecked();
+  // Return the buffer
+  info.GetReturnValue().Set(buffer);
+}
+
+void SecurityBuffer::Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target) {
+  // Define a new function template
+  Local<FunctionTemplate> t = Nan::New<FunctionTemplate>(New);
+  t->InstanceTemplate()->SetInternalFieldCount(1);
+  t->SetClassName(Nan::New<String>("SecurityBuffer").ToLocalChecked());
+
+  // Class methods
+  Nan::SetPrototypeMethod(t, "toBuffer", ToBuffer);
+
+  // Set persistent
+  constructor_template.Reset(t);
+
+  // Set the symbol
+  target->ForceSet(Nan::New<String>("SecurityBuffer").ToLocalChecked(), t->GetFunction());
+}

http://git-wip-us.apache.org/repos/asf/couchdb-nmo/blob/753f1767/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/wrappers/security_buffer.h
----------------------------------------------------------------------
diff --git a/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/wrappers/security_buffer.h b/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/wrappers/security_buffer.h
new file mode 100644
index 0000000..0c97d56
--- /dev/null
+++ b/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/wrappers/security_buffer.h
@@ -0,0 +1,48 @@
+#ifndef SECURITY_BUFFER_H
+#define SECURITY_BUFFER_H
+
+#include <node.h>
+#include <node_object_wrap.h>
+#include <v8.h>
+
+#define SECURITY_WIN32 1
+
+#include <winsock2.h>
+#include <windows.h>
+#include <sspi.h>
+#include <nan.h>
+
+using namespace v8;
+using namespace node;
+
+class SecurityBuffer : public Nan::ObjectWrap {
+  public:
+    SecurityBuffer(uint32_t security_type, size_t size);
+    SecurityBuffer(uint32_t security_type, size_t size, void *data);
+    ~SecurityBuffer();
+
+    // Internal values
+    void *data;
+    size_t size;
+    uint32_t security_type;
+    SecBuffer sec_buffer;
+
+    // Has instance check
+    static inline bool HasInstance(Local<Value> val) {
+      if (!val->IsObject()) return false;
+      Local<Object> obj = val->ToObject();
+      return Nan::New(constructor_template)->HasInstance(obj);
+    };
+
+    // Functions available from V8
+    static void Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target);
+    static NAN_METHOD(ToBuffer);
+
+    // Constructor used for creating new Long objects from C++
+    static Nan::Persistent<FunctionTemplate> constructor_template;
+
+  private:
+    static NAN_METHOD(New);
+};
+
+#endif
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/couchdb-nmo/blob/753f1767/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/wrappers/security_buffer.js
----------------------------------------------------------------------
diff --git a/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/wrappers/security_buffer.js b/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/wrappers/security_buffer.js
new file mode 100644
index 0000000..4996163
--- /dev/null
+++ b/node_modules/couchbulkimporter/node_modules/mongodb/node_modules/mongodb-core/node_modules/kerberos/lib/win32/wrappers/security_buffer.js
@@ -0,0 +1,12 @@
+var SecurityBufferNative = require('../../../build/Release/kerberos').SecurityBuffer;
+
+// Add some attributes
+SecurityBufferNative.VERSION  = 0;
+SecurityBufferNative.EMPTY    = 0;
+SecurityBufferNative.DATA     = 1;
+SecurityBufferNative.TOKEN    = 2;
+SecurityBufferNative.PADDING  = 9;
+SecurityBufferNative.STREAM   = 10;
+
+// Export the modified class
+exports.SecurityBuffer = SecurityBufferNative;
\ No newline at end of file