File: gss_context.hh

package info (click to toggle)
pdns-recursor 4.0.4-1+deb9u3~bpo8+1
  • links: PTS, VCS
  • area: main
  • in suites: jessie-backports
  • size: 5,484 kB
  • sloc: cpp: 36,380; sh: 11,771; makefile: 305; xml: 37
file content (184 lines) | stat: -rw-r--r-- 6,294 bytes parent folder | download | duplicates (3)
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
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
/*
 * This file is part of PowerDNS or dnsdist.
 * Copyright -- PowerDNS.COM B.V. and its contributors
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of version 2 of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * In addition, for the avoidance of any doubt, permission is granted to
 * link this program with OpenSSL and to (re)distribute the binaries
 * produced as the result of such linking.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
#ifndef GSS_CONTEXT_HH
#define GSS_CONTEXT_HH
#pragma once

#ifdef ENABLE_GSS_TSIG
#include <gssapi/gssapi.h>
#include <gssapi/gssapi_krb5.h>
#include <gssapi/gssapi_ext.h>
#endif

//! Generic errors
enum GssContextError {
  GSS_CONTEXT_NO_ERROR,
  GSS_CONTEXT_UNSUPPORTED,
  GSS_CONTEXT_NOT_FOUND,
  GSS_CONTEXT_NOT_INITIALIZED,
  GSS_CONTEXT_INVALID,
  GSS_CONTEXT_EXPIRED,
  GSS_CONTEXT_ALREADY_INITIALIZED
};

//! GSS context types
enum GssContextType {
  GSS_CONTEXT_NONE,
  GSS_CONTEXT_INIT,
  GSS_CONTEXT_ACCEPT
};

class GssSecContext;

/*! Class for representing GSS names, such as host/host.domain.com@REALM.
*/
class GssName {
public:
  //! Initialize to empty name
  GssName() {
    setName("");
  };

  //! Initilize using specific name
  GssName(const std::string& name) {
    setName(name);
  };

  //! Parse name into native representation
  bool setName(const std::string& name) {
#ifdef ENABLE_GSS_TSIG
    gss_buffer_desc buffer;
    d_name = GSS_C_NO_NAME;

    if (!name.empty()) {
      buffer.length = name.size();
      buffer.value = (void*)name.c_str();
      d_maj = gss_import_name(&d_min, &buffer, (gss_OID)GSS_KRB5_NT_PRINCIPAL_NAME, &d_name);
      return d_maj == GSS_S_COMPLETE;
    }

    return true;
#endif
    return false;
  };

  ~GssName() {
#ifdef ENABLE_GSS_TSIG
     if (d_name != GSS_C_NO_NAME)
       gss_release_name(&d_min, &d_name);
#endif
  };

  //! Compare two Gss Names, if no gss support is compiled in, returns false always
  //! This is not necessarely same as string comparison between two non-parsed names
  bool operator==(const GssName& rhs) {
#ifdef ENABLE_GSS_TSIG
    OM_uint32 maj,min;
    int result;
    maj = gss_compare_name(&min, d_name, rhs.d_name, &result);
    return (maj == GSS_S_COMPLETE && result != 0);
#endif
    return false;
  }

  //! Compare two Gss Names, if no gss support is compiled in, returns false always
  //! This is not necessarely same as string comparison between two non-parsed names
  bool match(const std::string& name) {
#ifdef ENABLE_GSS_TSIG
    OM_uint32 maj,min;
    int result;
    gss_name_t comp;
    gss_buffer_desc buffer;
    buffer.length = name.size();
    buffer.value = (void*)name.c_str();
    maj = gss_import_name(&min, &buffer, (gss_OID)GSS_KRB5_NT_PRINCIPAL_NAME, &comp);
    if (maj != GSS_S_COMPLETE)
      throw PDNSException("Could not import " + name + ": " + std::to_string(maj) + string(",") + std::to_string(min));
    // do comparison
    maj = gss_compare_name(&min, d_name, comp, &result);
    gss_release_name(&min, &comp);
    return (maj == GSS_S_COMPLETE && result != 0);
#else
   return false;
#endif
  };

  //! Check if GSS name was parsed successfully.
  bool valid() {
#ifdef ENABLE_GSS_TSIG
    return d_maj == GSS_S_COMPLETE;
#else
    return false;
#endif
  }
private:
#ifdef ENABLE_GSS_TSIG
  OM_uint32 d_maj,d_min;
  gss_name_t d_name;
#endif
};

class GssContext {
public:
  static bool supported(); //<! Returns true if GSS is supported in the first place
  GssContext(); //<! Construct new GSS context with random name
  GssContext(const DNSName& label); //<! Create or open existing named context

  void setLocalPrincipal(const std::string& name); //<! Set our gss name
  bool getLocalPrincipal(std::string& name); //<! Get our name
  void setPeerPrincipal(const std::string& name); //<! Set remote name (do not use after negotiation)
  bool getPeerPrincipal(std::string &name); //<! Return remote name, returns actual name after negotatioan

  void generateLabel(const std::string& suffix); //<! Generate random context name using suffix (such as mydomain.com)
  void setLabel(const DNSName& label); //<! Set context name to this label
  const DNSName& getLabel() { return d_label; } //<! Return context name

  bool init(const std::string &input, std::string& output); //<! Perform GSS Initiate Security Context handshake
  bool accept(const std::string &input, std::string& output); //<! Perform GSS Acccept Security Context handshake
  bool destroy(); //<! Release the cached context
  bool expired(); //<! Check if context is expired
  bool valid(); //<! Check if context is valid

  bool sign(const std::string &input, std::string& output); //<! Sign something using gss
  bool verify(const std::string &input, const std::string &signature); //<! Validate gss signature with something

  GssContextError getError(); //<! Get error
  const std::vector<std::string> getErrorStrings() { return d_gss_errors; } //<! Get native error texts
 private:
  void release(); //<! Release context
  void initialize(); //<! Initialize context
#ifdef ENABLE_GSS_TSIG
  void processError(const string& method, OM_uint32 maj, OM_uint32 min); //<! Process and fill error text vector
#endif
  DNSName d_label; //<! Context name
  std::string d_peerPrincipal; //<! Remote name
  std::string d_localPrincipal; //<! Our name
  GssContextError d_error; //<! Context error
  GssContextType d_type; //<! Context type
  std::vector<std::string> d_gss_errors; //<! Native error string(s)
  boost::shared_ptr<GssSecContext> d_ctx; //<! Attached security context
};

bool gss_add_signature(const DNSName& context, const std::string& message, std::string& mac); //<! Create signature
bool gss_verify_signature(const DNSName& context, const std::string& message, const std::string& mac); //<! Validate signature

#endif