1 /* 2 *---------------------------------------------------------------------------- 3 * 4 * krb5wrap.h 5 * 6 * (C) 2004-2006 Dan Perry (dperry@pppl.gov) 7 * (C) 2006 Brian Elliott Finley (finley@anl.gov) 8 * (C) 2009-2010 Doug Engert (deengert@anl.gov) 9 * (C) 2010 James Y Knight (foom@fuhm.net) 10 * (C) 2010-2013 Ken Dreyer <ktdreyer at ktdreyer.com> 11 * (C) 2012-2017 Mark Proehl <mark at mproehl.net> 12 * (C) 2012-2017 Olaf Flebbe <of at oflebbe.de> 13 * (C) 2013-2017 Daniel Kobras <d.kobras at science-computing.de> 14 * 15 This program is free software; you can redistribute it and/or modify 16 it under the terms of the GNU General Public License as published by 17 the Free Software Foundation; either version 2 of the License, or 18 (at your option) any later version. 19 20 This program is distributed in the hope that it will be useful, 21 but WITHOUT ANY WARRANTY; without even the implied warranty of 22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 GNU General Public License for more details. 24 25 You should have received a copy of the GNU General Public License 26 along with this program; if not, write to the Free Software 27 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 28 * 29 *----------------------------------------------------------------------------- 30 */ 31 32 extern krb5_context g_context; 33 34 void krb5_error_exit( const char *func, int err_code); 35 void krb5_warn( const char *func, int err_code); 36 37 void 38 initialize_g_context(); 39 40 void 41 destroy_g_context(); 42 43 class KRB5Principal; 44 45 class KRB5Keytab { 46 krb5_keytab m_keytab; 47 48 // make it non copyable 49 KRB5Keytab(const KRB5Keytab&); 50 const KRB5Keytab& operator=(const KRB5Keytab&); 51 52 public: KRB5Keytab(const std::string & keytab_name)53 KRB5Keytab(const std::string &keytab_name) : m_keytab() { 54 krb5_error_code ret = krb5_kt_resolve(g_context, keytab_name.c_str(), &m_keytab); 55 if (ret) { 56 throw KRB5Exception("krb5_kt_resolve", ret); 57 } 58 } 59 ~KRB5Keytab()60 ~KRB5Keytab() { 61 krb5_error_code ret = krb5_kt_close(g_context, m_keytab); 62 if (ret) { 63 krb5_warn("krb5_kt_close", ret); 64 } 65 } 66 67 void addEntry(const KRB5Principal &princ, krb5_kvno kvno, krb5_keyblock &keyblock); 68 void addEntry(const KRB5Principal &princ, krb5_kvno kvno, krb5_enctype enctype, 69 const std::string &password, const std::string &salt); 70 71 void removeEntry(const KRB5Principal &princ, krb5_kvno kvno, krb5_enctype enctype); 72 get()73 krb5_keytab get() { return m_keytab; } 74 75 /* Defined below... */ 76 class cursor; 77 }; 78 79 class KRB5Creds { 80 krb5_creds m_creds; 81 82 // make it non copyable 83 KRB5Creds(const KRB5Creds&); 84 const KRB5Creds& operator=(const KRB5Creds&); 85 86 public: KRB5Creds()87 KRB5Creds() : m_creds() {} 88 KRB5Creds(KRB5Principal &principal, KRB5Keytab &keytab, const char *tkt_service=NULL); 89 KRB5Creds(KRB5Principal &principal, const std::string &password, const char *tkt_service=NULL); ~KRB5Creds()90 ~KRB5Creds() { 91 krb5_free_cred_contents(g_context, &m_creds); 92 memset(&m_creds, 0, sizeof(m_creds)); 93 } 94 get()95 krb5_creds *get() { return &m_creds; } 96 move_from(KRB5Creds & other)97 void move_from(KRB5Creds &other) { 98 m_creds = other.m_creds; 99 memset(&other.m_creds, 0, sizeof(m_creds)); 100 } 101 }; 102 103 class KRB5CCache { 104 krb5_ccache m_ccache; 105 106 // make it non copyable 107 KRB5CCache(const KRB5CCache&); 108 const KRB5CCache& operator=(const KRB5CCache&); 109 110 public: defaultName()111 static const char *defaultName() { 112 return krb5_cc_default_name(g_context); 113 } 114 KRB5CCache(const char * cc_name)115 KRB5CCache(const char *cc_name) : m_ccache() { 116 krb5_error_code ret = krb5_cc_resolve(g_context, cc_name, &m_ccache); 117 if (ret) 118 throw KRB5Exception("krb5_cc_resolve", ret); 119 } 120 ~KRB5CCache()121 ~KRB5CCache() { 122 krb5_cc_close(g_context, m_ccache); 123 } 124 get()125 krb5_ccache get() { return m_ccache; } 126 127 void initialize(KRB5Principal &principal); 128 void store(KRB5Creds &creds); 129 }; 130 131 132 class KRB5Principal { 133 friend class KRB5Keytab::cursor; 134 135 krb5_principal m_princ; 136 KRB5Principal()137 KRB5Principal() : m_princ() {} 138 reset_no_free(krb5_principal princ)139 void reset_no_free(krb5_principal princ) { 140 m_princ = princ; 141 } 142 143 // make it non copyable 144 KRB5Principal(const KRB5Principal&); 145 const KRB5Principal& operator=(const KRB5Principal&); 146 147 public: KRB5Principal(krb5_principal princ_raw)148 KRB5Principal(krb5_principal princ_raw) : m_princ(princ_raw) {} 149 KRB5Principal(KRB5CCache & ccache)150 KRB5Principal(KRB5CCache &ccache) : m_princ() { 151 krb5_error_code ret = krb5_cc_get_principal(g_context, ccache.get(), &m_princ); 152 if (ret) 153 throw KRB5Exception("krb5_cc_get_principal", ret); 154 } 155 KRB5Principal(std::string principal_name)156 KRB5Principal(std::string principal_name) : m_princ() { 157 krb5_error_code ret = krb5_parse_name(g_context, principal_name.c_str(), &m_princ); 158 if (ret) 159 throw KRB5Exception("krb5_parse_name", ret); 160 } ~KRB5Principal()161 ~KRB5Principal() { 162 if (m_princ) 163 krb5_free_principal(g_context, m_princ); 164 } 165 get()166 krb5_principal get() const { return m_princ; } 167 std::string name(); 168 }; 169 170 class KRB5Keytab::cursor { 171 KRB5Keytab &m_keytab; 172 krb5_kt_cursor m_cursor; 173 krb5_keytab_entry m_entry; 174 175 /* Duplicates part of entry, but oh well. */ 176 KRB5Principal m_princ; 177 178 // make it non copyable 179 cursor(const cursor&); 180 const cursor& operator=(const cursor&); 181 bool m_ok; 182 public: 183 cursor(KRB5Keytab &keytab); 184 ~cursor(); 185 bool next(); 186 void reset(); 187 principal()188 KRB5Principal &principal() { return m_princ; } kvno()189 krb5_kvno kvno() const { return m_entry.vno; } enctype()190 krb5_enctype enctype() const { 191 #ifdef HEIMDAL 192 return static_cast<krb5_enctype>(m_entry.keyblock.keytype); 193 #else 194 return m_entry.key.enctype; 195 #endif 196 } 197 timestamp()198 krb5_timestamp timestamp() const { return m_entry.timestamp; } 199 key()200 krb5_keyblock key() const { 201 #ifdef HEIMDAL 202 return m_entry.keyblock; 203 #else 204 return m_entry.key; 205 #endif 206 } 207 }; 208 209 class KRB5KeytabEntry { 210 private: 211 std::string m_principal; 212 krb5_timestamp m_timestamp; 213 krb5_kvno m_kvno; 214 krb5_enctype m_enctype; 215 krb5_keyblock m_keyblock; 216 217 public: KRB5KeytabEntry(krb5_principal principal,krb5_timestamp timestamp,krb5_kvno kvno,krb5_enctype enctype,krb5_keyblock keyblock)218 KRB5KeytabEntry(krb5_principal principal, 219 krb5_timestamp timestamp, 220 krb5_kvno kvno, 221 krb5_enctype enctype, 222 krb5_keyblock keyblock) : m_principal(KRB5Principal(principal).name()), 223 m_timestamp(timestamp), 224 m_kvno(kvno), 225 m_enctype(enctype), 226 m_keyblock(keyblock) { 227 krb5_error_code ret = krb5_copy_keyblock_contents(g_context, &keyblock, &m_keyblock); 228 if (ret) { 229 throw KRB5Exception("krb5_copy_keyblock_contents", ret); 230 } 231 }; 232 KRB5KeytabEntry(KRB5Keytab::cursor & cursor)233 KRB5KeytabEntry(KRB5Keytab::cursor& cursor) : m_principal(cursor.principal().name()), 234 m_timestamp(cursor.timestamp()), 235 m_kvno(cursor.kvno()), 236 m_enctype(cursor.enctype()), 237 m_keyblock(cursor.key()) { 238 krb5_keyblock tmp = cursor.key(); 239 krb5_error_code ret = krb5_copy_keyblock_contents(g_context, &tmp, &m_keyblock); 240 if (ret) { 241 throw KRB5Exception("krb5_copy_keyblock_contents", ret); 242 } 243 }; 244 245 const KRB5KeytabEntry& operator=(const KRB5KeytabEntry& keytab_entry) { 246 m_principal = keytab_entry.m_principal; 247 m_timestamp = keytab_entry.m_timestamp; 248 m_kvno = keytab_entry.m_kvno; 249 m_enctype = keytab_entry.m_enctype; 250 m_keyblock = keytab_entry.m_keyblock; 251 252 krb5_error_code ret = krb5_copy_keyblock_contents(g_context, 253 &keytab_entry.m_keyblock, 254 &m_keyblock); 255 if (ret) { 256 throw KRB5Exception("krb5_copy_keyblock_contents", ret); 257 } 258 259 return *this; 260 }; 261 KRB5KeytabEntry(const KRB5KeytabEntry & keytab_entry)262 KRB5KeytabEntry(const KRB5KeytabEntry &keytab_entry) { 263 (void) operator=(keytab_entry); 264 }; 265 266 ~KRB5KeytabEntry()267 ~KRB5KeytabEntry() { krb5_free_keyblock_contents(g_context, &m_keyblock); }; 268 principal()269 std::string principal() { return m_principal; }; timestamp()270 krb5_timestamp timestamp() { return m_timestamp; }; kvno()271 krb5_kvno kvno() { return m_kvno; }; enctype()272 krb5_enctype enctype() { return m_enctype; }; keyblock()273 krb5_keyblock keyblock() { return m_keyblock; }; 274 275 bool operator < (const KRB5KeytabEntry& other) const { 276 return m_timestamp < other.m_timestamp; 277 }; 278 }; 279