1 /*
2  *----------------------------------------------------------------------------
3  *
4  * msktutil.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 #ifndef __msktutil_h__
33 #define __msktutil_h__
34 
35 
36 #include "config.h"
37 
38 #include <stdio.h>
39 #include <stdarg.h>
40 #include <fcntl.h>
41 #include <string.h>
42 #include <unistd.h>
43 #include <signal.h>
44 #include <ctype.h>
45 #include <stdlib.h>
46 #include <errno.h>
47 #include <time.h>
48 #include <limits.h>
49 #include <netdb.h>
50 #include <netinet/in.h>
51 #include <sys/socket.h>
52 #include <sys/utsname.h>
53 #include <ldap.h>
54 #include <list>
55 
56 #ifdef HAVE_COM_ERR_H
57 # ifdef COM_ERR_NEEDS_EXTERN_C
58   extern "C" {
59 # endif
60 #include <com_err.h>
61 # ifdef COM_ERR_NEEDS_EXTERN_C
62  }
63 # endif
64 #endif
65 #include <krb5.h>
66 
67 
68 #include <stdexcept>
69 #include <string>
70 #include <vector>
71 #include <memory>
72 
73 #ifndef PACKAGE_NAME
74 #define PACKAGE_NAME "msktutil"
75 #endif
76 #define PASSWORD_LEN                    63
77 #define MAX_HOSTNAME_LEN                255
78 #define MAX_TRIES                       10
79 #define MAX_SAM_ACCOUNT_LEN             20
80 #define MAX_DEF_MACH_PASS_LEN           14
81 #define MAX_DOMAIN_CONTROLLERS          20
82 
83 
84 #ifndef TMP_DIR
85 #define TMP_DIR                         "/tmp"
86 #endif
87 
88 
89 /* In case it's not in krb5.h */
90 #ifndef MAX_KEYTAB_NAME_LEN
91 #define  MAX_KEYTAB_NAME_LEN            1100
92 #endif
93 
94 /* From SAM.H */
95 #define UF_WORKSTATION_TRUST_ACCOUNT    0x00001000
96 #define UF_ACCOUNT_DISABLE              0x00000002
97 #define UF_NORMAL_ACCOUNT               0x00000200
98 #define UF_DONT_EXPIRE_PASSWORD         0x00010000
99 #define UF_TRUSTED_FOR_DELEGATION       0x00080000
100 #define UF_USE_DES_KEY_ONLY             0x00200000
101 #define UF_NO_AUTH_DATA_REQUIRED        0x02000000
102 
103 /* for msDs-supportedEncryptionTypes  bit defines */
104 #define MS_KERB_ENCTYPE_DES_CBC_CRC             0x01
105 #define MS_KERB_ENCTYPE_DES_CBC_MD5             0x02
106 #define MS_KERB_ENCTYPE_RC4_HMAC_MD5            0x04
107 
108 /* Define these if the system supports them, otherwise define to 0. */
109 #if HAVE_DECL_ENCTYPE_AES128_CTS_HMAC_SHA1_96
110 #define MS_KERB_ENCTYPE_AES128_CTC_HMAC_SHA1_96 0x08
111 #else
112 #define MS_KERB_ENCTYPE_AES128_CTC_HMAC_SHA1_96 0
113 #endif
114 
115 #if HAVE_DECL_ENCTYPE_AES128_CTS_HMAC_SHA1_96
116 #define MS_KERB_ENCTYPE_AES256_CTS_HMAC_SHA1_96 0x10
117 #else
118 #define MS_KERB_ENCTYPE_AES256_CTS_HMAC_SHA1_96 0
119 #endif
120 
121 /* Some KVNO Constansts */
122 #define KVNO_FAILURE                    -1
123 #define KVNO_WIN_2000                   0
124 
125 /* Ways we can authenticate */
126 enum auth_types {
127     AUTH_NONE = 0,
128     AUTH_FROM_SAM_KEYTAB,
129     AUTH_FROM_SAM_UPPERCASE_KEYTAB,
130     AUTH_FROM_HOSTNAME_KEYTAB,
131     AUTH_FROM_PASSWORD,
132     AUTH_FROM_USER_CREDS,
133     AUTH_FROM_SUPPLIED_PASSWORD,
134     AUTH_FROM_SUPPLIED_EXPIRED_PASSWORD,
135     AUTH_FROM_EXPLICIT_KEYTAB,
136 };
137 
138 class LDAPConnection;
139 
140 enum msktutil_val {
141     VALUE_OFF = 0,
142     VALUE_ON = 1,
143     VALUE_IGNORE = 2
144 };
145 
146 extern int g_verbose;
147 
148 enum msktutil_mode {
149     MODE_NONE = 0,
150     MODE_CREATE,
151     MODE_UPDATE,
152     MODE_AUTO_UPDATE,
153     MODE_FLUSH,
154     MODE_CLEANUP,
155     MODE_PRECREATE,
156     MODE_DELETE
157 };
158 
159 
160 class msktutil_flags {
161 public:
162     std::string keytab_file;
163     std::string keytab_writename;
164     std::string keytab_readname;
165     std::string keytab_auth_princ;
166     std::string ldap_ou;
167     std::string hostname;
168     std::string description;
169     std::string server;
170     std::string realm_name;
171     std::string lower_realm_name;
172     std::string base_dn;
173     std::string sAMAccountName;
174     std::string sAMAccountName_nodollar;
175     std::string sAMAccountName_uppercase;
176     std::string password;
177     bool password_from_cmdline;
178     std::string userPrincipalName;
179     std::string old_account_password;
180     std::string site;
181     LDAPConnection* ldap;
182     std::string ad_computerDn;
183     std::string ad_dnsHostName;
184     std::vector<std::string> ad_principals;
185 
186     bool set_userPrincipalName;
187     bool no_reverse_lookups;
188     bool no_canonical_name;
189     bool server_behind_nat;
190     bool set_samba_secret;
191     bool check_replication;
192     bool dont_change_password;
193 
194     msktutil_val dont_expire_password;
195     msktutil_val dont_update_dnshostname;
196     msktutil_val disable_account;
197     msktutil_val no_pac;
198     msktutil_val delegate;
199     unsigned int ad_userAccountControl; /* value AD has now */
200     int ad_enctypes;    /* if msDs-supportedEncryptionTypes in AD */
201     unsigned int ad_supportedEncryptionTypes; /* value AD has now */
202     int enctypes;       /* if --enctypes parameter was set */
203     unsigned int supportedEncryptionTypes;
204 
205     int auth_type;
206     bool user_creds_only;
207     bool use_service_account;
208     bool allow_weak_crypto;
209     bool password_expired;
210     int auto_update_interval;
211     krb5_kvno kvno;
212     int cleanup_days;
213     int cleanup_enctype;
214     msktutil_flags();
215 
216 private:
217     msktutil_flags operator=(const msktutil_flags& other);
218     msktutil_flags(const msktutil_flags& other);
219     ~msktutil_flags();
220 };
221 
222 class msktutil_exec {
223 public:
224     msktutil_mode mode;
225     std::vector<std::string> add_principals;
226     std::vector<std::string> remove_principals;
227 
228     msktutil_exec();
229 
230     ~msktutil_exec();
231     void set_mode(msktutil_mode mode);
232 };
233 
234 
235 class Globals {
236     msktutil_flags* _flags;
237     msktutil_exec* _exec;
238     static Globals *instance;
239 
240 public:
241     static Globals* get();
flags()242     static msktutil_flags *flags() {
243         return Globals::get()->_flags;
244     }
exec()245     static msktutil_exec *exec() {
246         return Globals::get()->_exec;
247     }
248     void set_supportedEncryptionTypes(char * value);
249 };
250 
251 /* Prototypes */
252 extern std::string create_default_machine_password(const std::string &sAMAccountName);
253 extern void ldap_cleanup(msktutil_flags *);
254 extern void init_password(msktutil_flags *);
255 extern std::string get_default_hostname(bool no_canonical_name = false);
256 extern void get_default_keytab(msktutil_flags *);
257 extern std::string get_salt(msktutil_flags *);
258 extern void get_default_ou(msktutil_flags *);
259 
260 extern void ldap_get_base_dn(msktutil_flags *);
261 extern std::string complete_hostname(const std::string &,
262                                      bool no_canonical_name = false);
263 extern std::string get_default_samaccountname(msktutil_flags *);
264 extern std::string get_short_hostname(msktutil_flags *);
265 extern int flush_keytab(msktutil_flags *);
266 extern void cleanup_keytab(msktutil_flags *);
267 extern void update_keytab(msktutil_flags *);
268 extern void add_keytab_entries(msktutil_flags *);
269 extern void remove_keytab_entries(msktutil_flags *,std::vector<std::string>);
270 extern void add_principal_keytab(const std::string &, msktutil_flags *);
271 extern int ldap_flush_principals(msktutil_flags *);
272 extern int set_password(msktutil_flags *);
273 extern krb5_kvno ldap_get_kvno(msktutil_flags *);
274 extern std::string ldap_get_pwdLastSet(msktutil_flags *);
275 extern std::vector<std::string> ldap_list_principals(msktutil_flags *);
276 extern int ldap_add_principal(const std::string &, msktutil_flags *);
277 int ldap_remove_principal(const std::string &principal, msktutil_flags *flags);
278 extern std::string get_dc_host(const std::string &realm_name, const std::string &site_name,
279                                const bool);
280 extern std::string get_host_os();
281 extern bool ldap_check_account(msktutil_flags *);
282 extern void ldap_create_account(msktutil_flags *);
283 extern void create_fake_krb5_conf(msktutil_flags *);
284 extern void remove_fake_krb5_conf();
285 extern void remove_ccache();
286 int find_working_creds(msktutil_flags *flags);
287 bool get_creds(msktutil_flags *flags);
288 int generate_new_password(msktutil_flags *flags);
289 
290 /* Verbose messages */
291 #define VERBOSE(text...) if (g_verbose) { fprintf(stdout, " -- %s: ", __FUNCTION__); fprintf(stdout, ## text); fprintf(stdout, "\n"); }
292 
293 /* Fatal error */
294 void error_exit(const char *text);
295 
296 /* To be used by higher level error messages, like krb5 */
297 void v_error_exit(const char* format, ...);
298 
299 /* printf into a C++ string. */
300 std::string sform(const char* format, ...);
301 
302 class Exception : public std::exception
303 {
304   protected:
305     std::string m_message;
306 
307     /* Prohibit assignment */
308     Exception& operator=(const Exception&);
309 
310   public:
311     /* Constructors */
312 
313     /* Default construction with no message uses "Exception" */
Exception()314     Exception() : m_message("Exception") { }
Exception(char const * simple_string)315     explicit Exception(char const * simple_string) : m_message(simple_string) {}
Exception(const std::string & str)316     explicit Exception(const std::string &str) : m_message(str) {}
Exception(const Exception & src)317     Exception(const Exception& src) : exception(), m_message(src.m_message)  {}
318 
~Exception()319     virtual ~Exception() throw() {};
what()320     char const * what() const throw() { return m_message.c_str(); }
321 };
322 
323 class KRB5Exception : public Exception
324 {
325   protected:
326     krb5_error_code m_err;
327   public:
KRB5Exception(const std::string & func,krb5_error_code err)328     explicit KRB5Exception(const std::string &func, krb5_error_code err) :
329         Exception(sform("Error: %s failed (%s)", func.c_str(), error_message(err)))
330     { m_err = err; }
err()331     krb5_error_code err() const throw() { return m_err; }
332 
333 };
334 
335 class LDAPException : public Exception
336 {
337   public:
LDAPException(const std::string & func,int err)338     explicit LDAPException(const std::string &func, int err) :
339         Exception(sform("Error: %s failed (%s)", func.c_str(), ldap_err2string(err)))
340     {}
341 };
342 
343 #ifdef __GNUC__
344 #define ATTRUNUSED __attribute__((unused))
345 #else
346 #define ATTRUNUSED
347 #endif
348 
349 
350 #include "krb5wrap.h"
351 #include "ldapconnection.h"
352 #include "msktname.h"
353 
354 
355 
356 #endif
357 
358