dse-driver 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +15 -0
- data/.yardopts +13 -0
- data/README.md +72 -0
- data/ext/gss_api_context/extconf.rb +27 -0
- data/ext/gss_api_context/gss_api_context.c +129 -0
- data/ext/gss_api_context/kerberosgss.c +407 -0
- data/ext/gss_api_context/kerberosgss.h +71 -0
- data/lib/dse.rb +104 -0
- data/lib/dse/auth/providers/gss_api.rb +160 -0
- data/lib/dse/auth/providers/password.rb +56 -0
- data/lib/dse/cluster.rb +99 -0
- data/lib/dse/geometry/line_string.rb +181 -0
- data/lib/dse/geometry/point.rb +179 -0
- data/lib/dse/geometry/polygon.rb +196 -0
- data/lib/dse/graph.rb +18 -0
- data/lib/dse/graph/duration.rb +131 -0
- data/lib/dse/graph/edge.rb +74 -0
- data/lib/dse/graph/options.rb +194 -0
- data/lib/dse/graph/path.rb +54 -0
- data/lib/dse/graph/result.rb +85 -0
- data/lib/dse/graph/result_set.rb +77 -0
- data/lib/dse/graph/statement.rb +118 -0
- data/lib/dse/graph/vertex.rb +107 -0
- data/lib/dse/graph/vertex_property.rb +66 -0
- data/lib/dse/load_balancing/policies/host_targeting.rb +102 -0
- data/lib/dse/session.rb +106 -0
- data/lib/dse/statements.rb +15 -0
- data/lib/dse/statements/host_targeting.rb +50 -0
- data/lib/dse/util.rb +12 -0
- data/lib/dse/util/endian_buffer.rb +37 -0
- data/lib/dse/version.rb +12 -0
- metadata +123 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
M2YwYzhhNTk0YzgxZTFkMzg2NGQyZWI0MDkyYmIxZTg4OWQ3OGZhZA==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
YTQ2NWY1NDJjMTRiY2U5OGVhNWVjNTYxYTc3YjAxOTM3NmEyMDA3ZQ==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
NGEyZTY1NmMxMThiZTY0YjJlZmQxMzE2MmUxY2ZkODUwNGUyOWVmZjZkNTIw
|
10
|
+
NjQ3OWI3NDJiMjJhMTM3ODkxOGEzMGZhNmRjYjdhMzI5YjMzNWY0ZjZiZTFj
|
11
|
+
ZjcyNzlkMTU0YjIyNDRmODQ2Yjk3ODU3ODc3Yzk1NDdkY2ZmNzk=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
OGU0MTJkOTNmMzQ0YzgzNGNlNWMwMjQ1MDllNzhkNTcxYWQ5NTFhZTc4NTc2
|
14
|
+
NTc4NTljNDczNzQyOThlNDk5NTc3NjcwNzAwYmI0MjUyMjc1YTkyNjFmM2M5
|
15
|
+
YTVmZTZjZGMzMGU5ZTY2NzcwNzVmY2JhYWQ0ZGRhZTQ0YzRmODM=
|
data/.yardopts
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
--no-private
|
2
|
+
--markup markdown
|
3
|
+
--type-tag expected_errors:"Expected Errors"
|
4
|
+
--tag jira_ticket:"JIRA Ticket"
|
5
|
+
--type-tag expected_result:"Expected Result"
|
6
|
+
--tag test_assumptions:"Test Assumptions"
|
7
|
+
--tag test_category:"Test Category"
|
8
|
+
|
9
|
+
lib/**/*.rb
|
10
|
+
integration/**/*.rb
|
11
|
+
-- README
|
12
|
+
|
13
|
+
load_plugins: true
|
data/README.md
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
# DataStax Enterprise Ruby Driver
|
2
|
+
|
3
|
+
*NOTE: The DataStax Enterprise Ruby Driver can be used solely with DataStax Enterprise. Please consult [the license](http://www.datastax.com/terms/datastax-dse-driver-license-terms).*
|
4
|
+
|
5
|
+
This driver is built on top of the [DataStax Ruby driver for Apache Cassandra](http://docs.datastax.com/en/latest-ruby-driver/ruby-driver/whatsNew.html)
|
6
|
+
and enhanced for the adaptive data management and mixed workload capabilities
|
7
|
+
provided by DSE. Therefore a lot of the underlying concepts are the same.
|
8
|
+
|
9
|
+
## Documentation
|
10
|
+
Driver documentation can be found [here](http://docs.datastax.com/en/latest-dse-ruby-driver/ruby-driver/whatsNew.html).
|
11
|
+
|
12
|
+
In particular, you'll find our [Features](http://docs.datastax.com/en/latest-dse-ruby-driver/supplemental/features) and
|
13
|
+
[API](http://docs.datastax.com/en/latest-dse-ruby-driver/supplemental/api) sections very enlightening.
|
14
|
+
|
15
|
+
## Feedback Requested
|
16
|
+
*Help us focus our efforts!* [Provide your input](http://goo.gl/forms/pCs8PTpHLf) on the Ruby Driver
|
17
|
+
Platform and Runtime Survey (we kept it short).
|
18
|
+
|
19
|
+
If you find an issue, please file an issue in our [public JIRA](https://datastax-oss.atlassian.net/browse/RUBY).
|
20
|
+
*Please be sure to specify the affects-version (DSE-1.X.Y).*
|
21
|
+
|
22
|
+
You can also post questions in [our forum](https://groups.google.com/a/lists.datastax.com/forum/#!forum/ruby-driver-user).
|
23
|
+
|
24
|
+
## Features
|
25
|
+
|
26
|
+
This driver exposes the following features of DSE 5.0:
|
27
|
+
|
28
|
+
* <a href="features/graph#graph">Graph</a>
|
29
|
+
* <a href="features/authentication#authentication">Authentication</a> with nodes running DSE
|
30
|
+
* <a href="features/geospatial#geospatial-types">Geospatial types</a>
|
31
|
+
|
32
|
+
Note that this driver is fully compatible with previous versions of DataStax Enterprise.
|
33
|
+
|
34
|
+
## Installation
|
35
|
+
The driver is named dse-driver on rubygems.org and can easily be installed with Bundler or the gem program. It will
|
36
|
+
download the appropriate Cassandra driver as well.
|
37
|
+
|
38
|
+
## Upgrade
|
39
|
+
The driver is intended to have the same look and feel as the core driver to make upgrading from the core driver
|
40
|
+
trivial. The only change is to replace references to the <code>Cassandra</code> module with <code>Dse</code> when
|
41
|
+
creating the cluster object:
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
require 'dse'
|
45
|
+
|
46
|
+
# This returns a Dse::Cluster instance
|
47
|
+
cluster = Dse.cluster
|
48
|
+
|
49
|
+
# This returns a Dse::Session instance
|
50
|
+
session = cluster.connect
|
51
|
+
rs = session.execute('select * from system.local')
|
52
|
+
```
|
53
|
+
|
54
|
+
## Determining driver versions
|
55
|
+
Within a script or irb, you can determine the exact versions of the dse and core drivers by accessing the VERSION
|
56
|
+
constant of the appropriate module:
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
require 'dse'
|
60
|
+
|
61
|
+
puts "Dse Driver Version: #{Dse::VERSION}"
|
62
|
+
puts "Cassandra Driver Version: #{Cassandra::VERSION}"
|
63
|
+
```
|
64
|
+
|
65
|
+
## Compatibility
|
66
|
+
Although this driver exposes new features introduced in DSE 5.0, it is fully compatible and supported for use with
|
67
|
+
previous versions of DSE.
|
68
|
+
|
69
|
+
## License
|
70
|
+
Copyright (C) 2016 DataStax Inc.
|
71
|
+
|
72
|
+
The full license terms are available at http://www.datastax.com/terms/datastax-dse-driver-license-terms
|
@@ -0,0 +1,27 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C) 2016 DataStax Inc.
|
3
|
+
#
|
4
|
+
# This software can be used solely with DataStax Enterprise. Please consult the license at
|
5
|
+
# http://www.datastax.com/terms/datastax-dse-driver-license-terms
|
6
|
+
#++
|
7
|
+
|
8
|
+
require 'mkmf'
|
9
|
+
|
10
|
+
LIBDIR = RbConfig::CONFIG['libdir']
|
11
|
+
INCLUDEDIR = RbConfig::CONFIG['includedir']
|
12
|
+
|
13
|
+
HEADER_DIRS = [INCLUDEDIR, '/usr/include'].freeze
|
14
|
+
|
15
|
+
LIB_DIRS = [LIBDIR, '/usr/lib'].freeze
|
16
|
+
|
17
|
+
dir_config('gssapi', HEADER_DIRS, LIB_DIRS)
|
18
|
+
|
19
|
+
abort 'no gssapi header' unless find_header('gssapi/gssapi.h')
|
20
|
+
|
21
|
+
abort 'gssapi library not found' unless find_library('gssapi_krb5', 'gss_release_buffer')
|
22
|
+
|
23
|
+
# On Mac at least, there are a lot of deprecated api warnings for gss_* functions. Disable that!
|
24
|
+
# rubocop:disable Style/GlobalVars
|
25
|
+
$CFLAGS << ' -Wno-deprecated'
|
26
|
+
|
27
|
+
create_makefile('gss_api_context')
|
@@ -0,0 +1,129 @@
|
|
1
|
+
//--
|
2
|
+
// Copyright (C) 2016 DataStax Inc.
|
3
|
+
//
|
4
|
+
// This software can be used solely with DataStax Enterprise. Please consult the license at
|
5
|
+
// http://www.datastax.com/terms/datastax-dse-driver-license-terms
|
6
|
+
//++
|
7
|
+
|
8
|
+
#include <ruby.h>
|
9
|
+
|
10
|
+
#include "kerberosgss.h"
|
11
|
+
|
12
|
+
//-----------------------------------------------------------------------------
|
13
|
+
// Platform-specific functions and macros
|
14
|
+
|
15
|
+
#ifdef _MSC_VER
|
16
|
+
typedef unsigned __int64 uint64_t;
|
17
|
+
typedef __int64 int64_t;
|
18
|
+
|
19
|
+
#else
|
20
|
+
#include <stdint.h>
|
21
|
+
#endif
|
22
|
+
|
23
|
+
VALUE e_GssError;
|
24
|
+
static void rb_free_context(gss_client_state* state);
|
25
|
+
|
26
|
+
static gss_client_state* get_state(VALUE self) {
|
27
|
+
gss_client_state* p;
|
28
|
+
Data_Get_Struct(self, gss_client_state, p);
|
29
|
+
return p;
|
30
|
+
}
|
31
|
+
|
32
|
+
static VALUE
|
33
|
+
rb_context_alloc(VALUE klass)
|
34
|
+
{
|
35
|
+
gss_client_state* state = ALLOC(gss_client_state);
|
36
|
+
state->response = NULL;
|
37
|
+
return Data_Wrap_Struct(klass, 0, rb_free_context, state);
|
38
|
+
}
|
39
|
+
|
40
|
+
static VALUE
|
41
|
+
rb_context_initialize(VALUE self, VALUE _service, VALUE _principal, VALUE _ticket_cache)
|
42
|
+
{
|
43
|
+
const char* service = StringValuePtr(_service);
|
44
|
+
const char* principal = _principal == Qnil ? NULL : StringValuePtr(_principal);
|
45
|
+
const char* ticket_cache = _ticket_cache == Qnil ? NULL : StringValuePtr(_ticket_cache);
|
46
|
+
|
47
|
+
long int gss_flags = GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG;
|
48
|
+
gss_client_state* state = get_state(self);
|
49
|
+
|
50
|
+
authenticate_gss_client_init(service, principal, ticket_cache, gss_flags, NULL, GSS_C_NO_OID, state);
|
51
|
+
|
52
|
+
return self;
|
53
|
+
}
|
54
|
+
|
55
|
+
static void
|
56
|
+
rb_free_context(gss_client_state* state)
|
57
|
+
{
|
58
|
+
if (state) {
|
59
|
+
authenticate_gss_client_clean(state);
|
60
|
+
xfree(state);
|
61
|
+
}
|
62
|
+
}
|
63
|
+
|
64
|
+
static VALUE
|
65
|
+
rb_context_response(VALUE self)
|
66
|
+
{
|
67
|
+
gss_client_state* state = get_state(self);
|
68
|
+
return state->response ? rb_str_new(state->response, state->responseLen) : Qnil;
|
69
|
+
}
|
70
|
+
|
71
|
+
static VALUE
|
72
|
+
rb_context_step(VALUE self, VALUE rb_challenge)
|
73
|
+
{
|
74
|
+
const char* challenge = StringValuePtr(rb_challenge);
|
75
|
+
int challenge_len = RSTRING_LEN(rb_challenge);
|
76
|
+
|
77
|
+
gss_client_state* state = get_state(self);
|
78
|
+
VALUE rc = INT2NUM(authenticate_gss_client_step(state, challenge, challenge_len));
|
79
|
+
return rb_ary_new3(2, rc, rb_context_response(self));
|
80
|
+
}
|
81
|
+
|
82
|
+
static VALUE
|
83
|
+
rb_context_wrap(VALUE self, VALUE rb_challenge)
|
84
|
+
{
|
85
|
+
const char* challenge = StringValuePtr(rb_challenge);
|
86
|
+
int challenge_len = RSTRING_LEN(rb_challenge);
|
87
|
+
|
88
|
+
gss_client_state* state = get_state(self);
|
89
|
+
authenticate_gss_client_wrap(state, challenge, challenge_len);
|
90
|
+
return rb_context_response(self);
|
91
|
+
}
|
92
|
+
|
93
|
+
static VALUE
|
94
|
+
rb_context_unwrap(VALUE self, VALUE rb_challenge)
|
95
|
+
{
|
96
|
+
const char* challenge = StringValuePtr(rb_challenge);
|
97
|
+
int challenge_len = RSTRING_LEN(rb_challenge);
|
98
|
+
|
99
|
+
gss_client_state* state = get_state(self);
|
100
|
+
authenticate_gss_client_unwrap(state, challenge, challenge_len);
|
101
|
+
return rb_context_response(self);
|
102
|
+
}
|
103
|
+
|
104
|
+
static VALUE
|
105
|
+
rb_context_user_name(VALUE self)
|
106
|
+
{
|
107
|
+
gss_client_state* state = get_state(self);
|
108
|
+
return state->username ? rb_str_new2(state->username) : Qnil;
|
109
|
+
}
|
110
|
+
|
111
|
+
void
|
112
|
+
Init_gss_api_context()
|
113
|
+
{
|
114
|
+
VALUE currentContainer;
|
115
|
+
|
116
|
+
currentContainer = rb_define_module_under(rb_cObject, "Dse");
|
117
|
+
currentContainer = rb_define_module_under(currentContainer, "Auth");
|
118
|
+
currentContainer = rb_define_module_under(currentContainer, "Providers");
|
119
|
+
currentContainer = rb_define_class_under(currentContainer, "GssApiContext", rb_cObject);
|
120
|
+
rb_define_alloc_func(currentContainer, rb_context_alloc);
|
121
|
+
rb_define_method(currentContainer, "initialize", rb_context_initialize, 3);
|
122
|
+
rb_define_method(currentContainer, "step", rb_context_step, 1);
|
123
|
+
rb_define_method(currentContainer, "response", rb_context_response, 0);
|
124
|
+
rb_define_method(currentContainer, "wrap", rb_context_wrap, 1);
|
125
|
+
rb_define_method(currentContainer, "unwrap", rb_context_unwrap, 1);
|
126
|
+
rb_define_method(currentContainer, "user_name", rb_context_user_name, 0);
|
127
|
+
|
128
|
+
e_GssError = rb_define_class_under(currentContainer, "Error", rb_eStandardError);
|
129
|
+
}
|
@@ -0,0 +1,407 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright (c) 2006-2016 Apple Inc. All rights reserved.
|
3
|
+
*
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
* you may not use this file except in compliance with the License.
|
6
|
+
* You may obtain a copy of the License at
|
7
|
+
*
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
*
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
* See the License for the specific language governing permissions and
|
14
|
+
* limitations under the License.
|
15
|
+
**/
|
16
|
+
|
17
|
+
#include "kerberosgss.h"
|
18
|
+
|
19
|
+
#include <stdio.h>
|
20
|
+
#include <stdlib.h>
|
21
|
+
#include <string.h>
|
22
|
+
#include <arpa/inet.h>
|
23
|
+
|
24
|
+
#include <ruby.h>
|
25
|
+
|
26
|
+
/* This is allocated in gss_api_context.c. */
|
27
|
+
extern VALUE e_GssError;
|
28
|
+
|
29
|
+
static void raise_gss_error(OM_uint32 err_maj, OM_uint32 err_min)
|
30
|
+
{
|
31
|
+
OM_uint32 maj_stat, min_stat;
|
32
|
+
OM_uint32 msg_ctx = 0;
|
33
|
+
gss_buffer_desc status_string;
|
34
|
+
char buf_maj[512];
|
35
|
+
char buf_min[512];
|
36
|
+
|
37
|
+
do {
|
38
|
+
maj_stat = gss_display_status(
|
39
|
+
&min_stat,
|
40
|
+
err_maj,
|
41
|
+
GSS_C_GSS_CODE,
|
42
|
+
GSS_C_NO_OID,
|
43
|
+
&msg_ctx,
|
44
|
+
&status_string
|
45
|
+
);
|
46
|
+
if (GSS_ERROR(maj_stat)) {
|
47
|
+
break;
|
48
|
+
}
|
49
|
+
strncpy(buf_maj, (char*) status_string.value, sizeof(buf_maj));
|
50
|
+
gss_release_buffer(&min_stat, &status_string);
|
51
|
+
|
52
|
+
if (!err_min) {
|
53
|
+
// There is no minor error to report.
|
54
|
+
break;
|
55
|
+
}
|
56
|
+
|
57
|
+
maj_stat = gss_display_status(
|
58
|
+
&min_stat,
|
59
|
+
err_min,
|
60
|
+
GSS_C_MECH_CODE,
|
61
|
+
GSS_C_NULL_OID,
|
62
|
+
&msg_ctx,
|
63
|
+
&status_string
|
64
|
+
);
|
65
|
+
if (! GSS_ERROR(maj_stat)) {
|
66
|
+
strncpy(buf_min, (char*) status_string.value, sizeof(buf_min));
|
67
|
+
gss_release_buffer(&min_stat, &status_string);
|
68
|
+
}
|
69
|
+
} while (!GSS_ERROR(maj_stat) && msg_ctx != 0);
|
70
|
+
|
71
|
+
if (err_min) {
|
72
|
+
rb_raise(e_GssError, "%s: %s", buf_maj, buf_min);
|
73
|
+
} else {
|
74
|
+
rb_raise(e_GssError, "%s", buf_maj);
|
75
|
+
}
|
76
|
+
}
|
77
|
+
|
78
|
+
void clear_response(gss_client_state* state)
|
79
|
+
{
|
80
|
+
if (state->response != NULL) {
|
81
|
+
free(state->response);
|
82
|
+
state->response = NULL;
|
83
|
+
state->responseLen = 0;
|
84
|
+
state->responseConf = 0;
|
85
|
+
}
|
86
|
+
}
|
87
|
+
|
88
|
+
static void save_response(gss_client_state* state, gss_buffer_desc* output_token, int conf)
|
89
|
+
{
|
90
|
+
OM_uint32 min_stat, maj_stat;
|
91
|
+
|
92
|
+
if (output_token->length) {
|
93
|
+
state->response = malloc(output_token->length);
|
94
|
+
memcpy(state->response, output_token->value, output_token->length);
|
95
|
+
state->responseLen = output_token->length;
|
96
|
+
state->responseConf = conf;
|
97
|
+
|
98
|
+
maj_stat = gss_release_buffer(&min_stat, output_token);
|
99
|
+
}
|
100
|
+
}
|
101
|
+
|
102
|
+
static void copy_challenge_to_token(const char* challenge, int challenge_len, gss_buffer_desc* token)
|
103
|
+
{
|
104
|
+
if (challenge && *challenge) {
|
105
|
+
// It would be great to just send the challenge along straight, but
|
106
|
+
// token->value is a non-const void*, so gss_* functions might
|
107
|
+
// mutate it.
|
108
|
+
|
109
|
+
token->value = malloc(challenge_len);
|
110
|
+
memcpy(token->value, challenge, challenge_len);
|
111
|
+
token->length = challenge_len;
|
112
|
+
}
|
113
|
+
}
|
114
|
+
|
115
|
+
void authenticate_gss_client_init(
|
116
|
+
const char* service, const char* principal, const char* ticket_cache, long int gss_flags,
|
117
|
+
gss_server_state* delegatestate, gss_OID mech_oid, gss_client_state* state
|
118
|
+
)
|
119
|
+
{
|
120
|
+
OM_uint32 maj_stat;
|
121
|
+
OM_uint32 min_stat;
|
122
|
+
gss_buffer_desc name_token = GSS_C_EMPTY_BUFFER;
|
123
|
+
gss_buffer_desc principal_token = GSS_C_EMPTY_BUFFER;
|
124
|
+
|
125
|
+
state->server_name = GSS_C_NO_NAME;
|
126
|
+
state->mech_oid = mech_oid;
|
127
|
+
state->context = GSS_C_NO_CONTEXT;
|
128
|
+
state->gss_flags = gss_flags;
|
129
|
+
state->client_creds = GSS_C_NO_CREDENTIAL;
|
130
|
+
state->username = NULL;
|
131
|
+
clear_response(state);
|
132
|
+
|
133
|
+
// Import server name first
|
134
|
+
name_token.length = strlen(service);
|
135
|
+
name_token.value = (char *)service;
|
136
|
+
|
137
|
+
maj_stat = gss_import_name(
|
138
|
+
&min_stat, &name_token, gss_krb5_nt_service_name, &state->server_name
|
139
|
+
);
|
140
|
+
|
141
|
+
if (GSS_ERROR(maj_stat)) {
|
142
|
+
raise_gss_error(maj_stat, min_stat);
|
143
|
+
}
|
144
|
+
|
145
|
+
if (ticket_cache && *ticket_cache) {
|
146
|
+
maj_stat = gss_krb5_ccache_name(&min_stat, ticket_cache, NULL);
|
147
|
+
if (GSS_ERROR(maj_stat)) {
|
148
|
+
raise_gss_error(maj_stat, min_stat);
|
149
|
+
}
|
150
|
+
}
|
151
|
+
|
152
|
+
// Use the delegate credentials if they exist
|
153
|
+
if (delegatestate && delegatestate->client_creds != GSS_C_NO_CREDENTIAL) {
|
154
|
+
state->client_creds = delegatestate->client_creds;
|
155
|
+
}
|
156
|
+
// If available use the principal to extract its associated credentials
|
157
|
+
else if (principal && *principal) {
|
158
|
+
gss_name_t name;
|
159
|
+
principal_token.length = strlen(principal);
|
160
|
+
principal_token.value = (char *)principal;
|
161
|
+
|
162
|
+
maj_stat = gss_import_name(
|
163
|
+
&min_stat, &principal_token, GSS_C_NT_USER_NAME, &name
|
164
|
+
);
|
165
|
+
if (GSS_ERROR(maj_stat)) {
|
166
|
+
raise_gss_error(maj_stat, min_stat);
|
167
|
+
}
|
168
|
+
maj_stat = gss_acquire_cred(
|
169
|
+
&min_stat, name, GSS_C_INDEFINITE, GSS_C_NO_OID_SET,
|
170
|
+
GSS_C_INITIATE, &state->client_creds, NULL, NULL
|
171
|
+
);
|
172
|
+
if (GSS_ERROR(maj_stat)) {
|
173
|
+
raise_gss_error(maj_stat, min_stat);
|
174
|
+
}
|
175
|
+
|
176
|
+
maj_stat = gss_release_name(&min_stat, &name);
|
177
|
+
if (GSS_ERROR(maj_stat)) {
|
178
|
+
raise_gss_error(maj_stat, min_stat);
|
179
|
+
}
|
180
|
+
}
|
181
|
+
}
|
182
|
+
|
183
|
+
int authenticate_gss_client_clean(gss_client_state *state)
|
184
|
+
{
|
185
|
+
OM_uint32 maj_stat;
|
186
|
+
OM_uint32 min_stat;
|
187
|
+
int ret = AUTH_GSS_COMPLETE;
|
188
|
+
|
189
|
+
if (state->context != GSS_C_NO_CONTEXT) {
|
190
|
+
maj_stat = gss_delete_sec_context(
|
191
|
+
&min_stat, &state->context, GSS_C_NO_BUFFER
|
192
|
+
);
|
193
|
+
}
|
194
|
+
if (state->server_name != GSS_C_NO_NAME) {
|
195
|
+
maj_stat = gss_release_name(&min_stat, &state->server_name);
|
196
|
+
}
|
197
|
+
if (
|
198
|
+
state->client_creds != GSS_C_NO_CREDENTIAL &&
|
199
|
+
! (state->gss_flags & GSS_C_DELEG_FLAG)
|
200
|
+
) {
|
201
|
+
maj_stat = gss_release_cred(&min_stat, &state->client_creds);
|
202
|
+
}
|
203
|
+
if (state->username != NULL) {
|
204
|
+
free(state->username);
|
205
|
+
state->username = NULL;
|
206
|
+
}
|
207
|
+
clear_response(state);
|
208
|
+
|
209
|
+
return ret;
|
210
|
+
}
|
211
|
+
|
212
|
+
int authenticate_gss_client_step(
|
213
|
+
gss_client_state* state, const char* challenge, int challenge_len
|
214
|
+
) {
|
215
|
+
OM_uint32 maj_stat;
|
216
|
+
OM_uint32 min_stat;
|
217
|
+
gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
|
218
|
+
gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
|
219
|
+
int ret = AUTH_GSS_CONTINUE;
|
220
|
+
|
221
|
+
// Always clear out the old response
|
222
|
+
clear_response(state);
|
223
|
+
|
224
|
+
// If there is a challenge (data from the server) we need to give it to GSS
|
225
|
+
copy_challenge_to_token(challenge, challenge_len, &input_token);
|
226
|
+
|
227
|
+
// Do GSSAPI step
|
228
|
+
maj_stat = gss_init_sec_context(
|
229
|
+
&min_stat,
|
230
|
+
state->client_creds,
|
231
|
+
&state->context,
|
232
|
+
state->server_name,
|
233
|
+
state->mech_oid,
|
234
|
+
(OM_uint32)state->gss_flags,
|
235
|
+
0,
|
236
|
+
GSS_C_NO_CHANNEL_BINDINGS,
|
237
|
+
&input_token,
|
238
|
+
NULL,
|
239
|
+
&output_token,
|
240
|
+
NULL,
|
241
|
+
NULL
|
242
|
+
);
|
243
|
+
|
244
|
+
if ((maj_stat != GSS_S_COMPLETE) && (maj_stat != GSS_S_CONTINUE_NEEDED)) {
|
245
|
+
if (output_token.value) {
|
246
|
+
gss_release_buffer(&min_stat, &output_token);
|
247
|
+
}
|
248
|
+
if (input_token.value) {
|
249
|
+
free(input_token.value);
|
250
|
+
}
|
251
|
+
raise_gss_error(maj_stat, min_stat);
|
252
|
+
}
|
253
|
+
|
254
|
+
ret = (maj_stat == GSS_S_COMPLETE) ? AUTH_GSS_COMPLETE : AUTH_GSS_CONTINUE;
|
255
|
+
|
256
|
+
// Grab the client response to send back to the server
|
257
|
+
save_response(state, &output_token, 0);
|
258
|
+
|
259
|
+
// Try to get the user name if we have completed all GSS operations
|
260
|
+
if (ret == AUTH_GSS_COMPLETE) {
|
261
|
+
gss_name_t gssuser = GSS_C_NO_NAME;
|
262
|
+
maj_stat = gss_inquire_context(&min_stat, state->context, &gssuser, NULL, NULL, NULL, NULL, NULL, NULL);
|
263
|
+
if (GSS_ERROR(maj_stat)) {
|
264
|
+
if (input_token.value) {
|
265
|
+
free(input_token.value);
|
266
|
+
}
|
267
|
+
if (output_token.value) {
|
268
|
+
gss_release_buffer(&min_stat, &output_token);
|
269
|
+
}
|
270
|
+
raise_gss_error(maj_stat, min_stat);
|
271
|
+
}
|
272
|
+
|
273
|
+
gss_buffer_desc name_token;
|
274
|
+
name_token.length = 0;
|
275
|
+
maj_stat = gss_display_name(&min_stat, gssuser, &name_token, NULL);
|
276
|
+
if (GSS_ERROR(maj_stat)) {
|
277
|
+
if (name_token.value) {
|
278
|
+
gss_release_buffer(&min_stat, &name_token);
|
279
|
+
}
|
280
|
+
gss_release_name(&min_stat, &gssuser);
|
281
|
+
|
282
|
+
if (input_token.value) {
|
283
|
+
free(input_token.value);
|
284
|
+
}
|
285
|
+
if (output_token.value) {
|
286
|
+
gss_release_buffer(&min_stat, &output_token);
|
287
|
+
}
|
288
|
+
raise_gss_error(maj_stat, min_stat);
|
289
|
+
} else {
|
290
|
+
if (state->username != NULL) {
|
291
|
+
free(state->username);
|
292
|
+
state->username = NULL;
|
293
|
+
}
|
294
|
+
state->username = (char *)malloc(name_token.length + 1);
|
295
|
+
strncpy(state->username, (char*) name_token.value, name_token.length);
|
296
|
+
state->username[name_token.length] = 0;
|
297
|
+
gss_release_buffer(&min_stat, &name_token);
|
298
|
+
gss_release_name(&min_stat, &gssuser);
|
299
|
+
}
|
300
|
+
}
|
301
|
+
|
302
|
+
end:
|
303
|
+
if (output_token.value) {
|
304
|
+
gss_release_buffer(&min_stat, &output_token);
|
305
|
+
}
|
306
|
+
if (input_token.value) {
|
307
|
+
free(input_token.value);
|
308
|
+
}
|
309
|
+
return ret;
|
310
|
+
}
|
311
|
+
|
312
|
+
int authenticate_gss_client_unwrap(
|
313
|
+
gss_client_state *state, const char *challenge, int challenge_len
|
314
|
+
) {
|
315
|
+
OM_uint32 maj_stat;
|
316
|
+
OM_uint32 min_stat;
|
317
|
+
gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
|
318
|
+
gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
|
319
|
+
int ret = AUTH_GSS_CONTINUE;
|
320
|
+
int conf = 0;
|
321
|
+
|
322
|
+
// Always clear out the old response
|
323
|
+
clear_response(state);
|
324
|
+
|
325
|
+
// If there is a challenge (data from the server) we need to give it to GSS
|
326
|
+
copy_challenge_to_token(challenge, challenge_len, &input_token);
|
327
|
+
|
328
|
+
// Do GSSAPI step
|
329
|
+
maj_stat = gss_unwrap(
|
330
|
+
&min_stat,
|
331
|
+
state->context,
|
332
|
+
&input_token,
|
333
|
+
&output_token,
|
334
|
+
&conf,
|
335
|
+
NULL
|
336
|
+
);
|
337
|
+
|
338
|
+
if (maj_stat != GSS_S_COMPLETE) {
|
339
|
+
if (output_token.value) {
|
340
|
+
gss_release_buffer(&min_stat, &output_token);
|
341
|
+
}
|
342
|
+
if (input_token.value) {
|
343
|
+
free(input_token.value);
|
344
|
+
}
|
345
|
+
raise_gss_error(maj_stat, min_stat);
|
346
|
+
} else {
|
347
|
+
ret = AUTH_GSS_COMPLETE;
|
348
|
+
}
|
349
|
+
|
350
|
+
// Grab the client response
|
351
|
+
save_response(state, &output_token, conf);
|
352
|
+
|
353
|
+
end:
|
354
|
+
if (output_token.value) {
|
355
|
+
gss_release_buffer(&min_stat, &output_token);
|
356
|
+
}
|
357
|
+
if (input_token.value) {
|
358
|
+
free(input_token.value);
|
359
|
+
}
|
360
|
+
return ret;
|
361
|
+
}
|
362
|
+
|
363
|
+
int authenticate_gss_client_wrap(
|
364
|
+
gss_client_state* state, const char* challenge, int challenge_len
|
365
|
+
) {
|
366
|
+
OM_uint32 maj_stat;
|
367
|
+
OM_uint32 min_stat;
|
368
|
+
gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
|
369
|
+
gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
|
370
|
+
int ret = AUTH_GSS_CONTINUE;
|
371
|
+
char buf[4096], server_conf_flags;
|
372
|
+
unsigned long buf_size;
|
373
|
+
|
374
|
+
// Always clear out the old response
|
375
|
+
clear_response(state);
|
376
|
+
|
377
|
+
copy_challenge_to_token(challenge, challenge_len, &input_token);
|
378
|
+
|
379
|
+
// Do GSSAPI wrap
|
380
|
+
maj_stat = gss_wrap(
|
381
|
+
&min_stat,
|
382
|
+
state->context,
|
383
|
+
0,
|
384
|
+
GSS_C_QOP_DEFAULT,
|
385
|
+
&input_token,
|
386
|
+
NULL,
|
387
|
+
&output_token
|
388
|
+
);
|
389
|
+
|
390
|
+
if (maj_stat != GSS_S_COMPLETE) {
|
391
|
+
if (output_token.value) {
|
392
|
+
gss_release_buffer(&min_stat, &output_token);
|
393
|
+
}
|
394
|
+
raise_gss_error(maj_stat, min_stat);
|
395
|
+
} else {
|
396
|
+
ret = AUTH_GSS_COMPLETE;
|
397
|
+
}
|
398
|
+
|
399
|
+
// Grab the client response to send back to the server
|
400
|
+
save_response(state, &output_token, 0);
|
401
|
+
|
402
|
+
end:
|
403
|
+
if (output_token.value) {
|
404
|
+
gss_release_buffer(&min_stat, &output_token);
|
405
|
+
}
|
406
|
+
return ret;
|
407
|
+
}
|