Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 291116
Collapse All | Expand All

(-)a/src/polkitagent/Makefile.am (-2 / +9 lines)
Lines 68-75 libpolkit_agent_1_la_LDFLAGS = -export-symbols-regex '(^polkit_.*)' Link Here
68
libexec_PROGRAMS = polkit-agent-helper-1
68
libexec_PROGRAMS = polkit-agent-helper-1
69
69
70
polkit_agent_helper_1_SOURCES = 					\
70
polkit_agent_helper_1_SOURCES = 					\
71
	polkitagenthelper.c						\
71
	polkitagenthelperprivate.c polkitagenthelperprivate.h		
72
	$(NULL)
72
73
if POLKIT_AUTHFW_PAM
74
polkit_agent_helper_1_SOURCES += polkitagenthelper-pam.c
75
endif
76
if POLKIT_AUTHFW_SHADOW
77
polkit_agent_helper_1_SOURCES += polkitagenthelper-shadow.c
78
endif
79
polkit_agent_helper_1_SOURCES += $(NULL)
73
80
74
polkit_agent_helper_1_CFLAGS  = 					\
81
polkit_agent_helper_1_CFLAGS  = 					\
75
        -D_POLKIT_COMPILATION                                  		\
82
        -D_POLKIT_COMPILATION                                  		\
(-)a/src/polkitagent/polkitagenthelper-pam.c (+288 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2008, 2010 Red Hat, Inc.
3
 *
4
 * This library is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU Lesser General Public
6
 * License as published by the Free Software Foundation; either
7
 * version 2 of the License, or (at your option) any later version.
8
 *
9
 * This library is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
 * Lesser General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU Lesser General
15
 * Public License along with this library; if not, write to the
16
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
17
 * Boston, MA 02111-1307, USA.
18
 *
19
 * Author: David Zeuthen <davidz@redhat.com>
20
 */
21
22
#include "config.h"
23
#include <stdio.h>
24
#include <stdlib.h>
25
#include <string.h>
26
#include <unistd.h>
27
#include <sys/types.h>
28
#include <sys/stat.h>
29
#include <syslog.h>
30
#include <security/pam_appl.h>
31
32
#include <polkit/polkit.h>
33
#include "polkitagenthelperprivate.h"
34
35
#ifdef HAVE_SOLARIS
36
#  define LOG_AUTHPRIV    (10<<3)
37
#endif
38
39
#ifndef HAVE_CLEARENV
40
extern char **environ;
41
42
static int
43
clearenv (void)
44
{
45
	if (environ != NULL)
46
		environ[0] = NULL;
47
	return 0;
48
}
49
#endif
50
51
/* Development aid: define PAH_DEBUG to get debugging output. Do _NOT_
52
 * enable this in production builds; it may leak passwords and other
53
 * sensitive information.
54
 */
55
#undef PAH_DEBUG
56
// #define PAH_DEBUG
57
58
59
static int conversation_function (int n, const struct pam_message **msg, struct pam_response **resp, void *data);
60
61
int
62
main (int argc, char *argv[])
63
{
64
  int rc;
65
  const char *user_to_auth;
66
  const char *cookie;
67
  struct pam_conv pam_conversation;
68
  pam_handle_t *pam_h;
69
  const void *authed_user;
70
71
  rc = 0;
72
  pam_h = NULL;
73
74
  /* clear the entire environment to avoid attacks using with libraries honoring environment variables */
75
  if (clearenv () != 0)
76
    goto error;
77
78
  /* set a minimal environment */
79
  setenv ("PATH", "/usr/sbin:/usr/bin:/sbin:/bin", 1);
80
81
  /* check that we are setuid root */
82
  if (geteuid () != 0)
83
    {
84
      fprintf (stderr, "polkit-agent-helper-1: needs to be setuid root\n");
85
      goto error;
86
    }
87
88
  openlog ("polkit-agent-helper-1", LOG_CONS | LOG_PID, LOG_AUTHPRIV);
89
90
  /* check for correct invocation */
91
  if (argc != 3)
92
    {
93
      syslog (LOG_NOTICE, "inappropriate use of helper, wrong number of arguments [uid=%d]", getuid ());
94
      fprintf (stderr, "polkit-agent-helper-1: wrong number of arguments. This incident has been logged.\n");
95
      goto error;
96
    }
97
98
  user_to_auth = argv[1];
99
  cookie = argv[2];
100
101
  if (getuid () != 0)
102
    {
103
      /* check we're running with a non-tty stdin */
104
      if (isatty (STDIN_FILENO) != 0)
105
        {
106
          syslog (LOG_NOTICE, "inappropriate use of helper, stdin is a tty [uid=%d]", getuid ());
107
          fprintf (stderr, "polkit-agent-helper-1: inappropriate use of helper, stdin is a tty. This incident has been logged.\n");
108
          goto error;
109
        }
110
    }
111
112
#ifdef PAH_DEBUG
113
  fprintf (stderr, "polkit-agent-helper-1: user to auth is '%s'.\n", user_to_auth);
114
#endif /* PAH_DEBUG */
115
116
  pam_conversation.conv        = conversation_function;
117
  pam_conversation.appdata_ptr = NULL;
118
119
  /* start the pam stack */
120
  rc = pam_start ("polkit-1",
121
                  user_to_auth,
122
                  &pam_conversation,
123
                  &pam_h);
124
  if (rc != PAM_SUCCESS)
125
    {
126
      fprintf (stderr, "polkit-agent-helper-1: pam_start failed: %s\n", pam_strerror (pam_h, rc));
127
      goto error;
128
    }
129
130
  /* set the requesting user */
131
  rc = pam_set_item (pam_h, PAM_RUSER, user_to_auth);
132
  if (rc != PAM_SUCCESS)
133
    {
134
      fprintf (stderr, "polkit-agent-helper-1: pam_set_item failed: %s\n", pam_strerror (pam_h, rc));
135
      goto error;
136
    }
137
138
  /* is user really user? */
139
  rc = pam_authenticate (pam_h, 0);
140
  if (rc != PAM_SUCCESS)
141
    {
142
      fprintf (stderr, "polkit-agent-helper-1: pam_authenticated failed: %s\n", pam_strerror (pam_h, rc));
143
      goto error;
144
    }
145
146
  /* permitted access? */
147
  rc = pam_acct_mgmt (pam_h, 0);
148
  if (rc != PAM_SUCCESS)
149
    {
150
      fprintf (stderr, "polkit-agent-helper-1: pam_acct_mgmt failed: %s\n", pam_strerror (pam_h, rc));
151
      goto error;
152
    }
153
154
  /* did we auth the right user? */
155
  rc = pam_get_item (pam_h, PAM_USER, &authed_user);
156
  if (rc != PAM_SUCCESS)
157
    {
158
      fprintf (stderr, "polkit-agent-helper-1: pam_get_item failed: %s\n", pam_strerror (pam_h, rc));
159
      goto error;
160
    }
161
162
  if (strcmp (authed_user, user_to_auth) != 0)
163
    {
164
      fprintf (stderr, "polkit-agent-helper-1: Tried to auth user '%s' but we got auth for user '%s' instead",
165
               user_to_auth, (const char *) authed_user);
166
      goto error;
167
    }
168
169
#ifdef PAH_DEBUG
170
  fprintf (stderr, "polkit-agent-helper-1: successfully authenticated user '%s'.\n", user_to_auth);
171
#endif /* PAH_DEBUG */
172
173
  pam_end (pam_h, rc);
174
  pam_h = NULL;
175
176
#ifdef PAH_DEBUG
177
  fprintf (stderr, "polkit-agent-helper-1: sending D-Bus message to PolicyKit daemon\n");
178
#endif /* PAH_DEBUG */
179
180
  /* now send a D-Bus message to the PolicyKit daemon that
181
   * includes a) the cookie; and b) the user we authenticated
182
   */
183
  if (!send_dbus_message (cookie, user_to_auth))
184
    {
185
#ifdef PAH_DEBUG
186
      fprintf (stderr, "polkit-agent-helper-1: error sending D-Bus message to PolicyKit daemon\n");
187
#endif /* PAH_DEBUG */
188
      goto error;
189
    }
190
191
#ifdef PAH_DEBUG
192
  fprintf (stderr, "polkit-agent-helper-1: successfully sent D-Bus message to PolicyKit daemon\n");
193
#endif /* PAH_DEBUG */
194
195
  fprintf (stdout, "SUCCESS\n");
196
  flush_and_wait();
197
  return 0;
198
199
error:
200
  if (pam_h != NULL)
201
    pam_end (pam_h, rc);
202
203
  fprintf (stdout, "FAILURE\n");
204
  flush_and_wait();
205
  return 1;
206
}
207
208
static int
209
conversation_function (int n, const struct pam_message **msg, struct pam_response **resp, void *data)
210
{
211
  struct pam_response *aresp;
212
  char buf[PAM_MAX_RESP_SIZE];
213
  int i;
214
215
  data = data;
216
  if (n <= 0 || n > PAM_MAX_NUM_MSG)
217
    return PAM_CONV_ERR;
218
219
  if ((aresp = calloc(n, sizeof *aresp)) == NULL)
220
    return PAM_BUF_ERR;
221
222
  for (i = 0; i < n; ++i)
223
    {
224
      aresp[i].resp_retcode = 0;
225
      aresp[i].resp = NULL;
226
      switch (msg[i]->msg_style)
227
        {
228
229
        case PAM_PROMPT_ECHO_OFF:
230
          fprintf (stdout, "PAM_PROMPT_ECHO_OFF ");
231
          goto conv1;
232
233
        case PAM_PROMPT_ECHO_ON:
234
          fprintf (stdout, "PAM_PROMPT_ECHO_ON ");
235
        conv1:
236
          fputs (msg[i]->msg, stdout);
237
          if (strlen (msg[i]->msg) > 0 && msg[i]->msg[strlen (msg[i]->msg) - 1] != '\n')
238
            fputc ('\n', stdout);
239
          fflush (stdout);
240
241
          if (fgets (buf, sizeof buf, stdin) == NULL)
242
            goto error;
243
244
          if (strlen (buf) > 0 &&
245
              buf[strlen (buf) - 1] == '\n')
246
            buf[strlen (buf) - 1] = '\0';
247
248
          aresp[i].resp = strdup (buf);
249
          if (aresp[i].resp == NULL)
250
            goto error;
251
          break;
252
253
        case PAM_ERROR_MSG:
254
          fprintf (stdout, "PAM_ERROR_MSG ");
255
          goto conv2;
256
257
        case PAM_TEXT_INFO:
258
          fprintf (stdout, "PAM_TEXT_INFO ");
259
        conv2:
260
          fputs (msg[i]->msg, stdout);
261
          if (strlen (msg[i]->msg) > 0 &&
262
              msg[i]->msg[strlen (msg[i]->msg) - 1] != '\n')
263
            fputc ('\n', stdout);
264
          fflush (stdout);
265
          break;
266
267
        default:
268
          goto error;
269
        }
270
    }
271
272
  *resp = aresp;
273
  return PAM_SUCCESS;
274
275
error:
276
277
  for (i = 0; i < n; ++i)
278
    {
279
      if (aresp[i].resp != NULL) {
280
        memset (aresp[i].resp, 0, strlen(aresp[i].resp));
281
        free (aresp[i].resp);
282
      }
283
    }
284
  memset (aresp, 0, n * sizeof *aresp);
285
  *resp = NULL;
286
  return PAM_CONV_ERR;
287
}
288
(-)a/src/polkitagent/polkitagenthelper-shadow.c (+204 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2008 Red Hat, Inc.
3
 * Copyright (C) 2009-2010 Andrew Psaltis <ampsaltis@gmail.com>
4
 *
5
 * This library is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU Lesser General Public
7
 * License as published by the Free Software Foundation; either
8
 * version 2 of the License, or (at your option) any later version.
9
 *
10
 * This library is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 * Lesser General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU Lesser General
16
 * Public License along with this library; if not, write to the
17
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18
 * Boston, MA 02111-1307, USA.
19
 *
20
 * Authors: Andrew Psaltis <ampsaltis@gmail.com>, based on
21
 *            polkitagenthelper.c which was written by
22
 *          David Zeuthen <davidz@redhat.com>
23
 */
24
25
#include "config.h"
26
#include <stdio.h>
27
#include <stdlib.h>
28
#include <string.h>
29
#include <unistd.h>
30
#include <sys/types.h>
31
#include <sys/stat.h>
32
#include <syslog.h>
33
#include <shadow.h>
34
#include <grp.h>
35
#include <pwd.h>
36
#include <time.h>
37
38
#include <polkit/polkit.h>
39
#include "polkitagenthelperprivate.h"
40
41
#ifdef HAVE_SOLARIS
42
#  define LOG_AUTHPRIV    (10<<3)
43
#endif
44
45
/* Development aid: define PAH_DEBUG to get debugging output. Do _NOT_
46
 * enable this in production builds; it may leak passwords and other
47
 * sensitive information.
48
 */
49
#undef PAH_DEBUG
50
//#define PAH_DEBUG
51
52
extern char *crypt ();
53
static int shadow_authenticate(struct spwd *shadow);
54
55
int
56
main (int argc, char *argv[])
57
{
58
  struct spwd *shadow;
59
  const char *user_to_auth;
60
  const char *cookie;
61
  time_t tm;
62
63
  /* clear the entire environment to avoid attacks with
64
     libraries honoring environment variables */
65
  if (clearenv () != 0)
66
    goto error;
67
68
  /* set a minimal environment */
69
  setenv ("PATH", "/usr/sbin:/usr/bin:/sbin:/bin", 1);
70
71
  /* check that we are setuid root */
72
  if (geteuid () != 0)
73
    {
74
    fprintf (stderr, "polkit-agent-helper-1: needs to be setuid root\n");
75
    goto error;
76
    }
77
78
  openlog ("polkit-agent-helper-1", LOG_CONS | LOG_PID, LOG_AUTHPRIV);
79
80
  /* check for correct invocation */
81
  if (argc != 3)
82
    {
83
      syslog (LOG_NOTICE, "inappropriate use of helper, wrong number of arguments [uid=%d]", getuid ());
84
      fprintf (stderr, "polkit-agent-helper-1: wrong number of arguments. This incident has been logged.\n");
85
      goto error;
86
    }
87
88
  if (getuid () != 0)
89
    {
90
    /* check we're running with a non-tty stdin */
91
    if (isatty (STDIN_FILENO) != 0)
92
      {
93
      syslog (LOG_NOTICE, "inappropriate use of helper, stdin is a tty [uid=%d]", getuid ());
94
      fprintf (stderr, "polkit-agent-helper-1: inappropriate use of helper, stdin is a tty. This incident has been logged.\n");
95
      goto error;
96
      }
97
    }
98
99
  user_to_auth = argv[1];
100
  cookie = argv[2];
101
102
#ifdef PAH_DEBUG
103
  fprintf (stderr, "polkit-agent-helper-1: user to auth is '%s'.\n", user_to_auth);
104
#endif /* PAH_DEBUG */
105
106
  /* Ask shadow about the user requesting authentication */
107
  if ((shadow = getspnam (user_to_auth)) == NULL)
108
    {
109
    syslog (LOG_NOTICE, "shadow file data information request for user %s [uid=%d] failed", user_to_auth, getuid());
110
    fprintf(stderr, "polkit-agent-helper-1: could not get shadow information for%.100s", user_to_auth);
111
    goto error;
112
    }
113
  
114
  /* Check the user's identity */
115
  if(!shadow_authenticate (shadow))
116
    {
117
    syslog (LOG_NOTICE, "authentication failure [uid=%d] trying to authenticate '%s'", getuid (), user_to_auth);
118
    fprintf (stderr, "polkit-agent-helper-1: authentication failure. This incident has been logged.\n");
119
    goto error;
120
    }
121
122
  /* Check whether the user's password has expired */
123
  time(&tm);
124
  if( (shadow->sp_lstchg + shadow->sp_max) * 60 * 60 * 24 >= tm)
125
    {
126
    syslog (LOG_NOTICE, "password expired for user '%s' [uid=%d] trying to authenticate", user_to_auth, getuid () );
127
    fprintf (stderr, "polkit-agent-helper-1: authorization failure. This incident has been logged.\n");
128
    }
129
130
  /* Check whether the user's password has aged (and account expired along
131
   * with it)
132
   */
133
  if( (shadow->sp_lstchg + shadow->sp_max + shadow->sp_inact) * 60 * 60 * 24           >= tm) 
134
    {
135
    syslog (LOG_NOTICE, "password aged for user '%s' [uid=%d] trying to authenticate", user_to_auth, getuid () );
136
    fprintf (stderr, "polkit-agent-helper-1: authorization failure. This incident has been logged.\n");
137
    }
138
139
  /* Check whether the user's account has expired */
140
  if(shadow->sp_expire * 60 * 60 * 24 >= tm) 
141
    {
142
    syslog (LOG_NOTICE, "account expired for user '%s' [uid=%d] trying to authenticate", user_to_auth, getuid () );
143
    fprintf (stderr, "polkit-agent-helper-1: authorization failure. This incident has been logged.\n");
144
     
145
    }
146
147
#ifdef PAH_DEBUG
148
  fprintf (stderr, "polkit-agent-helper-1: sending D-Bus message to PolicyKit daemon\n");
149
#endif /* PAH_DEBUG */
150
151
  /* now send a D-Bus message to the PolicyKit daemon that
152
   * includes a) the cookie; and b) the user we authenticated
153
   */
154
  if (!send_dbus_message (cookie, user_to_auth))
155
    {
156
#ifdef PAH_DEBUG
157
      fprintf (stderr, "polkit-agent-helper-1: error sending D-Bus message to PolicyKit daemon\n");
158
#endif /* PAH_DEBUG */
159
      goto error;
160
    }
161
162
#ifdef PAH_DEBUG
163
  fprintf (stderr, "polkit-agent-helper-1: successfully sent D-Bus message to PolicyKit daemon\n");
164
#endif /* PAH_DEBUG */
165
166
  fprintf (stdout, "SUCCESS\n");
167
  flush_and_wait();
168
  return 0;
169
170
error:
171
  sleep (2); /* Discourage brute force attackers */
172
  fprintf (stdout, "FAILURE\n");
173
  flush_and_wait();
174
  return 1;
175
}
176
177
static int
178
shadow_authenticate(struct spwd *shadow)
179
{
180
  /* Speak PAM to the daemon, thanks to David Zeuthen for the idea. */
181
  char passwd[256];
182
  fprintf(stdout, "PAM_PROMPT_ECHO_OFF password:\n");
183
  //fprintf(stderr, "PAM_PROMPT_ECHO_OFF password:\n");
184
  fflush(stdout);
185
  usleep (10 * 1000); /* since fflush(3) seems buggy */
186
187
  //fprintf(stderr, "Waiting for password...\n");
188
  if (fgets (passwd, sizeof (passwd), stdin) == NULL)
189
    goto error;
190
  //fprintf(stderr, "Got password\n");
191
192
  if (strlen (passwd) > 0 && passwd[strlen (passwd) - 1] == '\n')
193
    passwd[strlen (passwd) - 1] = '\0';
194
  //fprintf(stderr, "Checking password...\n");
195
  if (strcmp (shadow->sp_pwdp, crypt (passwd, shadow->sp_pwdp)) != 0)
196
    goto error;
197
  //fprintf(stderr, "Correct.\n");
198
  return 1;
199
error:
200
  //fprintf(stderr, "Something failed. :(\n");
201
  return 0;
202
}
203
204
//static int shadow_acct_mgmt(shadow
(-)a/src/polkitagent/polkitagenthelper.c (-339 lines)
Lines 1-339 Link Here
1
/*
2
 * Copyright (C) 2008 Red Hat, Inc.
3
 *
4
 * This library is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU Lesser General Public
6
 * License as published by the Free Software Foundation; either
7
 * version 2 of the License, or (at your option) any later version.
8
 *
9
 * This library is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
 * Lesser General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU Lesser General
15
 * Public License along with this library; if not, write to the
16
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
17
 * Boston, MA 02111-1307, USA.
18
 *
19
 * Author: David Zeuthen <davidz@redhat.com>
20
 */
21
22
#include "config.h"
23
#include <stdio.h>
24
#include <stdlib.h>
25
#include <string.h>
26
#include <unistd.h>
27
#include <sys/types.h>
28
#include <sys/stat.h>
29
#include <syslog.h>
30
#include <security/pam_appl.h>
31
32
#include <polkit/polkit.h>
33
34
#ifdef HAVE_SOLARIS
35
#  define LOG_AUTHPRIV    (10<<3)
36
#endif
37
38
#ifndef HAVE_CLEARENV
39
extern char **environ;
40
41
static int
42
clearenv (void)
43
{
44
	if (environ != NULL)
45
		environ[0] = NULL;
46
	return 0;
47
}
48
#endif
49
50
/* Development aid: define PAH_DEBUG to get debugging output. Do _NOT_
51
 * enable this in production builds; it may leak passwords and other
52
 * sensitive information.
53
 */
54
#undef PAH_DEBUG
55
// #define PAH_DEBUG
56
57
static gboolean send_dbus_message (const char *cookie, const char *user);
58
59
static int conversation_function (int n, const struct pam_message **msg, struct pam_response **resp, void *data);
60
61
int
62
main (int argc, char *argv[])
63
{
64
  int rc;
65
  const char *user_to_auth;
66
  const char *cookie;
67
  struct pam_conv pam_conversation;
68
  pam_handle_t *pam_h;
69
  const void *authed_user;
70
71
  rc = 0;
72
  pam_h = NULL;
73
74
  /* clear the entire environment to avoid attacks using with libraries honoring environment variables */
75
  if (clearenv () != 0)
76
    goto error;
77
78
  /* set a minimal environment */
79
  setenv ("PATH", "/usr/sbin:/usr/bin:/sbin:/bin", 1);
80
81
  /* check that we are setuid root */
82
  if (geteuid () != 0)
83
    {
84
      fprintf (stderr, "polkit-agent-helper-1: needs to be setuid root\n");
85
      goto error;
86
    }
87
88
  openlog ("polkit-agent-helper-1", LOG_CONS | LOG_PID, LOG_AUTHPRIV);
89
90
  /* check for correct invocation */
91
  if (argc != 3)
92
    {
93
      syslog (LOG_NOTICE, "inappropriate use of helper, wrong number of arguments [uid=%d]", getuid ());
94
      fprintf (stderr, "polkit-agent-helper-1: wrong number of arguments. This incident has been logged.\n");
95
      goto error;
96
    }
97
98
  user_to_auth = argv[1];
99
  cookie = argv[2];
100
101
  if (getuid () != 0)
102
    {
103
      /* check we're running with a non-tty stdin */
104
      if (isatty (STDIN_FILENO) != 0)
105
        {
106
          syslog (LOG_NOTICE, "inappropriate use of helper, stdin is a tty [uid=%d]", getuid ());
107
          fprintf (stderr, "polkit-agent-helper-1: inappropriate use of helper, stdin is a tty. This incident has been logged.\n");
108
          goto error;
109
        }
110
    }
111
112
#ifdef PAH_DEBUG
113
  fprintf (stderr, "polkit-agent-helper-1: user to auth is '%s'.\n", user_to_auth);
114
#endif /* PAH_DEBUG */
115
116
  pam_conversation.conv        = conversation_function;
117
  pam_conversation.appdata_ptr = NULL;
118
119
  /* start the pam stack */
120
  rc = pam_start ("polkit-1",
121
                  user_to_auth,
122
                  &pam_conversation,
123
                  &pam_h);
124
  if (rc != PAM_SUCCESS)
125
    {
126
      fprintf (stderr, "polkit-agent-helper-1: pam_start failed: %s\n", pam_strerror (pam_h, rc));
127
      goto error;
128
    }
129
130
  /* set the requesting user */
131
  rc = pam_set_item (pam_h, PAM_RUSER, user_to_auth);
132
  if (rc != PAM_SUCCESS)
133
    {
134
      fprintf (stderr, "polkit-agent-helper-1: pam_set_item failed: %s\n", pam_strerror (pam_h, rc));
135
      goto error;
136
    }
137
138
  /* is user really user? */
139
  rc = pam_authenticate (pam_h, 0);
140
  if (rc != PAM_SUCCESS)
141
    {
142
      fprintf (stderr, "polkit-agent-helper-1: pam_authenticated failed: %s\n", pam_strerror (pam_h, rc));
143
      goto error;
144
    }
145
146
  /* permitted access? */
147
  rc = pam_acct_mgmt (pam_h, 0);
148
  if (rc != PAM_SUCCESS)
149
    {
150
      fprintf (stderr, "polkit-agent-helper-1: pam_acct_mgmt failed: %s\n", pam_strerror (pam_h, rc));
151
      goto error;
152
    }
153
154
  /* did we auth the right user? */
155
  rc = pam_get_item (pam_h, PAM_USER, &authed_user);
156
  if (rc != PAM_SUCCESS)
157
    {
158
      fprintf (stderr, "polkit-agent-helper-1: pam_get_item failed: %s\n", pam_strerror (pam_h, rc));
159
      goto error;
160
    }
161
162
  if (strcmp (authed_user, user_to_auth) != 0)
163
    {
164
      fprintf (stderr, "polkit-agent-helper-1: Tried to auth user '%s' but we got auth for user '%s' instead",
165
               user_to_auth, (const char *) authed_user);
166
      goto error;
167
    }
168
169
#ifdef PAH_DEBUG
170
  fprintf (stderr, "polkit-agent-helper-1: successfully authenticated user '%s'.\n", user_to_auth);
171
#endif /* PAH_DEBUG */
172
173
  pam_end (pam_h, rc);
174
  pam_h = NULL;
175
176
#ifdef PAH_DEBUG
177
  fprintf (stderr, "polkit-agent-helper-1: sending D-Bus message to PolicyKit daemon\n");
178
#endif /* PAH_DEBUG */
179
180
  /* now send a D-Bus message to the PolicyKit daemon that
181
   * includes a) the cookie; and b) the user we authenticated
182
   */
183
  if (!send_dbus_message (cookie, user_to_auth))
184
    {
185
#ifdef PAH_DEBUG
186
      fprintf (stderr, "polkit-agent-helper-1: error sending D-Bus message to PolicyKit daemon\n");
187
#endif /* PAH_DEBUG */
188
      goto error;
189
    }
190
191
#ifdef PAH_DEBUG
192
  fprintf (stderr, "polkit-agent-helper-1: successfully sent D-Bus message to PolicyKit daemon\n");
193
#endif /* PAH_DEBUG */
194
195
  fprintf (stdout, "SUCCESS\n");
196
  fflush (stdout);
197
  fflush (stderr);
198
  usleep (10 * 1000); /* since fflush(3) seems buggy */
199
  return 0;
200
201
error:
202
  if (pam_h != NULL)
203
    pam_end (pam_h, rc);
204
205
  fprintf (stdout, "FAILURE\n");
206
  fflush (stdout);
207
  fflush (stderr);
208
  usleep (10 * 1000); /* since fflush(3) seems buggy */
209
  return 1;
210
}
211
212
static int
213
conversation_function (int n, const struct pam_message **msg, struct pam_response **resp, void *data)
214
{
215
  struct pam_response *aresp;
216
  char buf[PAM_MAX_RESP_SIZE];
217
  int i;
218
219
  data = data;
220
  if (n <= 0 || n > PAM_MAX_NUM_MSG)
221
    return PAM_CONV_ERR;
222
223
  if ((aresp = calloc(n, sizeof *aresp)) == NULL)
224
    return PAM_BUF_ERR;
225
226
  for (i = 0; i < n; ++i)
227
    {
228
      aresp[i].resp_retcode = 0;
229
      aresp[i].resp = NULL;
230
      switch (msg[i]->msg_style)
231
        {
232
233
        case PAM_PROMPT_ECHO_OFF:
234
          fprintf (stdout, "PAM_PROMPT_ECHO_OFF ");
235
          goto conv1;
236
237
        case PAM_PROMPT_ECHO_ON:
238
          fprintf (stdout, "PAM_PROMPT_ECHO_ON ");
239
        conv1:
240
          fputs (msg[i]->msg, stdout);
241
          if (strlen (msg[i]->msg) > 0 && msg[i]->msg[strlen (msg[i]->msg) - 1] != '\n')
242
            fputc ('\n', stdout);
243
          fflush (stdout);
244
245
          if (fgets (buf, sizeof buf, stdin) == NULL)
246
            goto error;
247
248
          if (strlen (buf) > 0 &&
249
              buf[strlen (buf) - 1] == '\n')
250
            buf[strlen (buf) - 1] = '\0';
251
252
          aresp[i].resp = strdup (buf);
253
          if (aresp[i].resp == NULL)
254
            goto error;
255
          break;
256
257
        case PAM_ERROR_MSG:
258
          fprintf (stdout, "PAM_ERROR_MSG ");
259
          goto conv2;
260
261
        case PAM_TEXT_INFO:
262
          fprintf (stdout, "PAM_TEXT_INFO ");
263
        conv2:
264
          fputs (msg[i]->msg, stdout);
265
          if (strlen (msg[i]->msg) > 0 &&
266
              msg[i]->msg[strlen (msg[i]->msg) - 1] != '\n')
267
            fputc ('\n', stdout);
268
          fflush (stdout);
269
          break;
270
271
        default:
272
          goto error;
273
        }
274
    }
275
276
  *resp = aresp;
277
  return PAM_SUCCESS;
278
279
error:
280
281
  for (i = 0; i < n; ++i)
282
    {
283
      if (aresp[i].resp != NULL) {
284
        memset (aresp[i].resp, 0, strlen(aresp[i].resp));
285
        free (aresp[i].resp);
286
      }
287
    }
288
  memset (aresp, 0, n * sizeof *aresp);
289
  *resp = NULL;
290
  return PAM_CONV_ERR;
291
}
292
293
static gboolean
294
send_dbus_message (const char *cookie, const char *user)
295
{
296
  PolkitAuthority *authority;
297
  PolkitIdentity *identity;
298
  GError *error;
299
  gboolean ret;
300
301
  ret = FALSE;
302
303
  error = NULL;
304
305
  g_type_init ();
306
307
  authority = polkit_authority_get ();
308
309
  identity = polkit_unix_user_new_for_name (user, &error);
310
  if (identity == NULL)
311
    {
312
      g_printerr ("Error constructing identity: %s\n", error->message);
313
      g_error_free (error);
314
      goto out;
315
    }
316
317
  if (!polkit_authority_authentication_agent_response_sync (authority,
318
                                                            cookie,
319
                                                            identity,
320
                                                            NULL,
321
                                                            &error))
322
    {
323
      g_printerr ("polkit-agent-helper-1: error response to PolicyKit daemon: %s\n", error->message);
324
      g_error_free (error);
325
      goto out;
326
    }
327
328
  ret = TRUE;
329
330
 out:
331
332
  if (identity != NULL)
333
    g_object_unref (identity);
334
335
  if (authority != NULL)
336
    g_object_unref (authority);
337
338
  return ret;
339
}
(-)a/src/polkitagent/polkitagenthelperprivate.c (+83 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2009-2010 Red Hat, Inc.
3
 *
4
 * This library is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU Lesser General Public
6
 * License as published by the Free Software Foundation; either
7
 * version 2 of the License, or (at your option) any later version.
8
 *
9
 * This library is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
 * Lesser General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU Lesser General
15
 * Public License along with this library; if not, write to the
16
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17
 * Boston, MA 02110-1301, USA.
18
 *
19
 * Authosr: David Zeuthen <davidz@redhat.com>,
20
 *          Andrew Psaltis <ampsaltis@gmail.com>
21
 */
22
23
#include "polkitagenthelperprivate.h"
24
#include <stdio.h>
25
26
gboolean
27
send_dbus_message (const char *cookie, const char *user)
28
{
29
  PolkitAuthority *authority;
30
  PolkitIdentity *identity;
31
  GError *error;
32
  gboolean ret;
33
34
  ret = FALSE;
35
36
  error = NULL;
37
38
  g_type_init ();
39
40
  authority = polkit_authority_get ();
41
42
  identity = polkit_unix_user_new_for_name (user, &error);
43
  if (identity == NULL)
44
    {
45
      g_printerr ("Error constructing identity: %s\n", error->message);
46
      g_error_free (error);
47
      goto out;
48
    }
49
50
  if (!polkit_authority_authentication_agent_response_sync (authority,
51
                                                            cookie,
52
                                                            identity,
53
                                                            NULL,
54
                                                            &error))
55
    {
56
      g_printerr ("polkit-agent-helper-1: error response to PolicyKit daemon: %s\n", error->message);
57
      g_error_free (error);
58
      goto out;
59
    }
60
61
  ret = TRUE;
62
63
 out:
64
65
  if (identity != NULL)
66
    g_object_unref (identity);
67
68
  if (authority != NULL)
69
    g_object_unref (authority);
70
71
  return ret;
72
}
73
74
/* fflush(3) stdin and stdout and wait a little bit.
75
 * This replaces the three-line commands at the bottom of
76
 * polkit-agent-helper-1's main() function. */
77
void
78
flush_and_wait ()
79
{
80
  fflush (stdout);
81
  fflush (stderr);
82
  usleep (10 * 1000); /* since fflush(3) seems buggy */
83
}
(-)a/src/polkitagent/polkitagenthelperprivate.h (+38 lines)
Line 0 Link Here
1
/*
2
 * Copyright (C) 2009-2010 Red Hat, Inc.
3
 *
4
 * This library is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU Lesser General Public
6
 * License as published by the Free Software Foundation; either
7
 * version 2 of the License, or (at your option) any later version.
8
 *
9
 * This library is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
 * Lesser General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU Lesser General
15
 * Public License along with this library; if not, write to the
16
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17
 * Boston, MA 02110-1301, USA.
18
 *
19
 * Authors: David Zeuthen <davidz@redhat.com>,
20
 *          Andrew Psaltis <ampsalits@gmail.com>
21
 */
22
#ifndef __POLKIT_AGENT_HELPER_PRIVATE_H
23
#define __POLKIT_AGENT_HELPER_PRIVATE_H
24
25
#include <polkit/polkit.h>
26
 
27
/* Development aid: define PAH_DEBUG to get debugging output. Do _NOT_
28
 * enable this in production builds; it may leak passwords and other
29
 * sensitive information.
30
 */
31
//#undef PAH_DEBUG
32
// #define PAH_DEBUG
33
34
gboolean send_dbus_message (const char *cookie, const char *user);
35
36
void flush_and_wait ();
37
38
#endif /* __POLKIT_AGENT_HELPER_PRIVATE_H */
(-)a/src/polkitagent/polkitagentsession.c (-1 / +3 lines)
Lines 348-361 io_watch_have_data (GIOChannel *channel, Link Here
348
  if (strlen (line) > 0 && line[strlen (line) - 1] == '\n')
348
  if (strlen (line) > 0 && line[strlen (line) - 1] == '\n')
349
    line[strlen (line) - 1] = '\0';
349
    line[strlen (line) - 1] = '\0';
350
350
351
  //g_debug ("Got '%s' from helper", line);
351
  g_debug ("Got '%s' from helper", line);
352
352
353
  if (g_str_has_prefix (line, "PAM_PROMPT_ECHO_OFF "))
353
  if (g_str_has_prefix (line, "PAM_PROMPT_ECHO_OFF "))
354
    {
354
    {
355
      //fprintf(stderr, "Got PAM_PROMPT_ECHO_OFF\n");
355
      g_signal_emit_by_name (session, "request", line + sizeof "PAM_PROMPT_ECHO_OFF " - 1, FALSE);
356
      g_signal_emit_by_name (session, "request", line + sizeof "PAM_PROMPT_ECHO_OFF " - 1, FALSE);
356
    }
357
    }
357
  else if (g_str_has_prefix (line, "PAM_PROMPT_ECHO_ON "))
358
  else if (g_str_has_prefix (line, "PAM_PROMPT_ECHO_ON "))
358
    {
359
    {
360
      //printf(stderr, "Got PAM_PROMPT_ECHO_ON\n");
359
      g_signal_emit_by_name (session, "request", line + sizeof "PAM_PROMPT_ECHO_ON " - 1, TRUE);
361
      g_signal_emit_by_name (session, "request", line + sizeof "PAM_PROMPT_ECHO_ON " - 1, TRUE);
360
    }
362
    }
361
  else if (g_str_has_prefix (line, "PAM_ERROR_MSG "))
363
  else if (g_str_has_prefix (line, "PAM_ERROR_MSG "))
(-)a/src/programs/pkexec.c (-1 / +6 lines)
Lines 34-40 Link Here
34
#include <grp.h>
34
#include <grp.h>
35
#include <pwd.h>
35
#include <pwd.h>
36
#include <errno.h>
36
#include <errno.h>
37
#ifdef POLKIT_AUTHFW_PAM
37
#include <security/pam_appl.h>
38
#include <security/pam_appl.h>
39
#endif /* POLKIT_AUTHFW_PAM */
38
#include <syslog.h>
40
#include <syslog.h>
39
#include <stdarg.h>
41
#include <stdarg.h>
40
42
Lines 115-120 log_message (gint level, Link Here
115
117
116
/* ---------------------------------------------------------------------------------------------------- */
118
/* ---------------------------------------------------------------------------------------------------- */
117
119
120
#ifdef POLKIT_AUTHFW_PAM
118
static int
121
static int
119
pam_conversation_function (int n,
122
pam_conversation_function (int n,
120
                           const struct pam_message **msg,
123
                           const struct pam_message **msg,
Lines 167-172 out: Link Here
167
    pam_end (pam_h, rc);
170
    pam_end (pam_h, rc);
168
  return ret;
171
  return ret;
169
}
172
}
173
#endif /*POLKIT_AUTHFW_PAM*/
170
174
171
/* ---------------------------------------------------------------------------------------------------- */
175
/* ---------------------------------------------------------------------------------------------------- */
172
176
Lines 742-752 main (int argc, char *argv[]) Link Here
742
   * TODO: The question here is whether we should clear the limits before applying them?
746
   * TODO: The question here is whether we should clear the limits before applying them?
743
   * As evident above, neither su(1) (and, for that matter, nor sudo(8)) does this.
747
   * As evident above, neither su(1) (and, for that matter, nor sudo(8)) does this.
744
   */
748
   */
749
#ifdef POLKIT_AUTHW_PAM
745
  if (!open_session (pw->pw_name))
750
  if (!open_session (pw->pw_name))
746
    {
751
    {
747
      goto out;
752
      goto out;
748
    }
753
    }
749
754
#endif /* POLKIT_AUTHFW_PAM */
750
  /* become the user */
755
  /* become the user */
751
  if (setgroups (0, NULL) != 0)
756
  if (setgroups (0, NULL) != 0)
752
    {
757
    {

Return to bug 291116