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
  
/* -*- c -*- 
 * $Id$ 
 * 
 * Kerberos support for Pike. 
 * 
 * 2004-05-12 Henrik Grubbström 
 * 
 * FIXME: Currently only minimal support, and only for Kerberos 5 (not 4). 
 */ 
 
#include "global.h" 
#include "config.h" 
 
#include "svalue.h" 
#include "module.h" 
#include "interpret.h" 
 
DECLARATIONS 
 
/* #define KRB_DEBUG */ 
 
#ifdef KRB_DEBUG 
#define KRB_FPRINTF(X)  fprintf X 
#else /* !KRB_DEBUG */ 
#define KRB_FPRINTF(X) 
#endif /* KRB_DEBUG */ 
 
#ifdef HAVE_KRB5 
 
#ifdef HAVE_KRB5_H 
#include <krb5.h> 
#else 
#ifdef HAVE_KERBEROSV5_KRB5_H 
#include <kerberosv5/krb5.h> 
#endif 
#endif 
 
PIKECLASS Context 
{ 
  CVAR krb5_context ctx; 
 
  INIT 
  { 
    krb5_error_code err_code; 
    if ((err_code = krb5_init_context(&THIS->ctx))) { 
      Pike_error("Failed to initialize context: %d\n", err_code); 
    } 
  } 
 
  EXIT 
    gc_trivial; 
  { 
    if (THIS->ctx) { 
      krb5_free_context(THIS->ctx); 
    } 
  } 
 
  PIKEFUN int(0..1) authenticate(string user, string password) 
    optflags OPT_EXTERNAL_DEPEND; 
  { 
    krb5_error_code err_code; 
    krb5_principal principal; 
    krb5_get_init_creds_opt get_creds_opt; 
    krb5_verify_init_creds_opt verify_creds_opt; 
    krb5_creds creds; 
    ONERROR err; 
 
    /* Hide the password from backtraces. */ 
    Pike_sp[0] = Pike_sp[1-args]; 
    Pike_sp[1-args].type = PIKE_T_INT; 
    Pike_sp[1-args].subtype = NUMBER_UNDEFINED; 
    Pike_sp[1-args].u.integer = 0; 
    Pike_sp++; 
    args++; 
 
    if (user->size_shift || password->size_shift) { 
      KRB_FPRINTF((stderr, "Wide password or user name.\n")); 
      pop_n_elems(args); 
      push_int(0); 
      return; 
    } 
 
    if ((err_code = krb5_parse_name(THIS->ctx, (const char *) STR0(user), 
                                    &principal))) { 
      KRB_FPRINTF((stderr, "Failed to parse user name: %d\n", err_code)); 
      pop_n_elems(args); 
      push_int(0); 
      return; 
    } 
 
    krb5_get_init_creds_opt_init(&get_creds_opt); 
    krb5_verify_init_creds_opt_init(&verify_creds_opt); 
 
    if ((err_code = krb5_get_init_creds_password(THIS->ctx, &creds, 
                                                 principal, 
                                                 (char *) STR0(password), 
                                                 krb5_prompter_posix, 
                                                 NULL, 0, NULL, 
                                                 &get_creds_opt))) { 
      KRB_FPRINTF((stderr, "Failed to get password credentials: %d.\n", 
                   err_code)); 
      pop_n_elems(args); 
      push_int(0); 
      return; 
    } 
 
    if ((err_code = krb5_verify_init_creds(THIS->ctx, &creds, 
                                           NULL, NULL, NULL, 
                                           &verify_creds_opt))) { 
      krb5_free_cred_contents(THIS->ctx, &creds); 
      KRB_FPRINTF((stderr, "Failed to verify credentials: %d.\n", err_code)); 
      pop_n_elems(args); 
      push_int(0); 
      return; 
    } 
 
    krb5_free_cred_contents(THIS->ctx, &creds); 
    KRB_FPRINTF((stderr, "Credentials ok.")); 
 
    pop_n_elems(args); 
    push_int(1); 
    return; 
  } 
} 
 
 
#endif /* HAVE_KRB5 */ 
 
PIKE_MODULE_INIT 
{ 
  INIT; 
} 
 
PIKE_MODULE_EXIT 
{ 
  EXIT; 
}