dse-driver 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}
|