~ubuntu-branches/ubuntu/edgy/network-manager-pptp/edgy

« back to all changes in this revision

Viewing changes to src/nm-pppd-plugin.c

  • Committer: Bazaar Package Importer
  • Author(s): Craig Box
  • Date: 2006-10-01 16:04:54 UTC
  • Revision ID: james.westby@ubuntu.com-20061001160454-3lepz9bs63bqtvfa
Tags: upstream-0.6.3+cvs20060819
ImportĀ upstreamĀ versionĀ 0.6.3+cvs20060819

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* nm-pptp-service - pptp (and other pppd) integration with NetworkManager
 
2
 *
 
3
 * Antony J Mee <eemynotna at gmail dot com>
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or modify
 
6
 * it under the terms of the GNU General Public License as published by
 
7
 * the Free Software Foundation; either version 2 of the License, or
 
8
 * (at your option) any later version.
 
9
 *
 
10
 * This program 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
 
13
 * GNU General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License
 
16
 * along with this program; if not, write to the Free Software
 
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
18
 *
 
19
 */
 
20
 
 
21
#include "pppd/pppd.h"
 
22
 
 
23
#include "pppd/fsm.h"
 
24
#include "pppd/ipcp.h"
 
25
#ifndef PPPD_VERSION
 
26
  #ifdef VERSION
 
27
    #define PPPD_VERSION VERSION
 
28
  #endif
 
29
#endif
 
30
 
 
31
#include <sys/types.h>
 
32
#include <unistd.h>
 
33
#include <glib.h>
 
34
#include <stdlib.h>
 
35
#include <stdio.h>
 
36
#include <string.h>
 
37
#include <regex.h>
 
38
#include <sys/socket.h>
 
39
#include <netinet/in.h>
 
40
#include <arpa/inet.h>
 
41
#include <dbus/dbus.h>
 
42
#include <dbus/dbus-glib-lowlevel.h>
 
43
#include <dbus/dbus-glib.h>
 
44
#include <NetworkManager/NetworkManager.h>
 
45
 
 
46
#include "nm-ppp-starter.h"
 
47
#include "nm-pppd-plugin.h"
 
48
#include "nm-utils.h"
 
49
 
 
50
typedef struct NmPPPData
 
51
{
 
52
  DBusConnection        *con;
 
53
  gboolean          got_auth_info;
 
54
  char              *auth_type;
 
55
  char              *username;
 
56
  char              *password;
 
57
  int               pppd_pid;
 
58
} NmPPPData;
 
59
 
 
60
char pppd_version[] = PPPD_VERSION;
 
61
 
 
62
NmPPPData plugin_data;
 
63
 
 
64
int plugin_init();
 
65
 
 
66
void nm_ip_up(void *opaque, int arg);
 
67
void nm_ip_down(void *opaque, int arg);
 
68
void nm_exit_notify(void *opaque, int arg);
 
69
 
 
70
int nm_chap_passwd_hook(char *user, char *passwd);
 
71
int nm_chap_check_hook(void);
 
72
 
 
73
void nm_notify_pid (NmPPPData *data);
 
74
void send_config_error (DBusConnection *con, const char *item);
 
75
gboolean nm_get_auth_items (NmPPPData *data);
 
76
gboolean nm_store_auth_info (NmPPPData *data, char **auth_items, int num_auth_items);
 
77
gboolean nm_dbus_prepare_connection(NmPPPData *data);
 
78
static DBusHandlerResult nm_dbus_message_handler (DBusConnection *con, DBusMessage *message, void *user_data);
 
79
void nm_dbus_kill_connection(NmPPPData *data);
 
80
 
 
81
gboolean nm_dbus_prepare_connection(NmPPPData *data)
 
82
{
 
83
//    DBusMessage *     message = NULL;
 
84
    DBusError           error;
 
85
//    DBusObjectPathVTable       vtable = { NULL, 
 
86
//                                        &nm_dbus_message_handler, 
 
87
//                                        NULL, NULL, NULL, NULL };
 
88
 
 
89
    g_return_val_if_fail (data != NULL, FALSE);
 
90
    if (data->con != NULL) return TRUE;
 
91
 
 
92
 
 
93
    dbus_error_init (&error);
 
94
    data->con = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
 
95
    if ((data->con == NULL) || dbus_error_is_set (&error))
 
96
      {
 
97
        info("Could not get the system bus.  Make sure the message bus daemon is running?");
 
98
        goto out;
 
99
      }
 
100
    dbus_connection_set_exit_on_disconnect (data->con, FALSE);
 
101
 
 
102
//    dbus_error_init (&error);
 
103
//    dbus_bus_request_name (data->con, NM_DBUS_SERVICE_PPP, 0, &error);
 
104
//    if (dbus_error_is_set (&error))
 
105
//      {
 
106
//        nm_warning ("Could not acquire the dbus service.  dbus_bus_request_name() says: '%s'", error.message);
 
107
//        goto out;
 
108
//      }
 
109
    
 
110
//    if (!dbus_connection_register_object_path (data->con, NM_DBUS_PATH_PPP, &vtable, data))
 
111
//      {
 
112
//        nm_warning ("Could not register a dbus handler for nm-ppp-service.  Not enough memory?");
 
113
//        dbus_connection_unref(data->con);
 
114
//        data->con = NULL;
 
115
//      }
 
116
out:
 
117
    if (dbus_error_is_set (&error))
 
118
      {
 
119
        dbus_error_free (&error);
 
120
        data->con = NULL;
 
121
      }
 
122
    if (data->con == NULL) return FALSE;
 
123
    return TRUE;
 
124
}
 
125
 
 
126
void nm_dbus_kill_connection(NmPPPData *data)
 
127
{
 
128
    g_return_if_fail (data != NULL);
 
129
 
 
130
    if (data->con != NULL)
 
131
      dbus_connection_unref(data->con);
 
132
    if (data->username!=NULL) g_free(data->username);
 
133
    if (data->password!=NULL) g_free(data->password);
 
134
}
 
135
 
 
136
/*
 
137
 * nm_dbus_message_handler
 
138
 *
 
139
 * Handle requests for our services.
 
140
 *
 
141
 */
 
142
static DBusHandlerResult nm_dbus_message_handler (DBusConnection *con, DBusMessage *message, void *user_data)
 
143
{
 
144
  NmPPPData                 *data = (NmPPPData *)user_data;
 
145
  const char            *method;
 
146
  const char            *path;
 
147
  DBusMessage           *reply = NULL;
 
148
  gboolean                       handled = TRUE;
 
149
 
 
150
  g_return_val_if_fail (data != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
 
151
  g_return_val_if_fail (con != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
 
152
  g_return_val_if_fail (message != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
 
153
 
 
154
  method = dbus_message_get_member (message);
 
155
  path = dbus_message_get_path (message);
 
156
 
 
157
  nm_info ("nm_dbus_message_handler() got method '%s' for path '%s'.", method, path); 
 
158
 
 
159
  handled = FALSE;
 
160
  
 
161
// reply:
 
162
  if (reply)
 
163
    {
 
164
      dbus_connection_send (con, reply, NULL);
 
165
      dbus_message_unref (reply);
 
166
    }
 
167
 
 
168
  return (handled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
 
169
}
 
170
 
 
171
 
 
172
int nm_chap_check_hook(void)
 
173
{
 
174
    plugin_data.pppd_pid=getpid();
 
175
    nm_notify_pid (&plugin_data);
 
176
 
 
177
    if (! nm_get_auth_items (&plugin_data))
 
178
      {
 
179
        return 0;
 
180
      }
 
181
 
 
182
    if (strcmp("CHAP",plugin_data.auth_type)!=0)
 
183
      {
 
184
        info("nm-pppd-plugin: No CHAP authentication available!");
 
185
        return 0;
 
186
      }
 
187
    
 
188
 
 
189
    info("nm-pppd-plugin: CHAP check hook.");
 
190
    return 1;
 
191
}
 
192
 
 
193
int nm_chap_passwd_hook(char *user, char *passwd)
 
194
{
 
195
    info("nm-pppd-plugin: CHAP credentials requested.");
 
196
 
 
197
    if (user == NULL)
 
198
      {
 
199
        info("nm-pppd-plugin: pppd didn't provide username buffer");
 
200
        return -1;
 
201
      }
 
202
 
 
203
    if (passwd == NULL)
 
204
      {
 
205
        info("nm-pppd-plugin: pppd didn't provide password buffer");
 
206
        return -1;
 
207
      }
 
208
 
 
209
    if (plugin_data.username == NULL)
 
210
      {
 
211
        info("nm-pppd-plugin: CHAP username not set");
 
212
        return -1;
 
213
      }
 
214
 
 
215
    if (plugin_data.password == NULL)
 
216
      {
 
217
        info("nm-pppd-plugin: CHAP password not set");
 
218
        return -1;
 
219
      }
 
220
 
 
221
    if (strlen(plugin_data.username) >= MAXNAMELEN)
 
222
      {
 
223
        info("nm-pppd-plugin: CHAP username too long!");
 
224
        return -1;
 
225
      }
 
226
 
 
227
    if (strlen(plugin_data.password) >= MAXSECRETLEN)
 
228
      {
 
229
        info("nm-pppd-plugin: CHAP password too long!");
 
230
        return -1;
 
231
      }
 
232
 
 
233
    strcpy(user, plugin_data.username);
 
234
    user[MAXNAMELEN-1]='\0';
 
235
    strcpy(passwd, plugin_data.password);
 
236
    passwd[MAXSECRETLEN-1]='\0';
 
237
//    info("nm-pppd-plugin: CHAP authenticating as '%s' with '%s'",user,passwd);
 
238
//
 
239
// Forget the username and password?
 
240
//
 
241
//    if (plugin_data.username!=NULL) g_free(plugin_data.username);
 
242
//    if (plugin_data.password!=NULL) g_free(plugin_data.password);
 
243
 
 
244
    return 0;
 
245
}
 
246
 
 
247
void nm_exit_notify(void *opaque, int arg)
 
248
{
 
249
  NmPPPData *data = (NmPPPData *)opaque;
 
250
 
 
251
  nm_dbus_kill_connection(data);
 
252
}
 
253
 
 
254
void nm_ip_down(void *opaque, int arg)
 
255
{   
 
256
//  DBusConnection *con = (DBusConnection *)opaque;
 
257
 
 
258
  return;
 
259
}
 
260
 
 
261
void nm_ip_up(void *opaque, int arg)
 
262
{
 
263
  NmPPPData *data = (NmPPPData *)opaque;
 
264
  DBusConnection *con = data->con;
 
265
  DBusMessage           *message;
 
266
 
 
267
  char *                str_ifname        = NULL;
 
268
//  guint32 *           uint_ip4_dns   = NULL;
 
269
  guint32               uint_ip4_dns1     = 0;
 
270
  guint32               uint_ip4_dns2     = 0;
 
271
  guint32               uint_ip4_dns_len  = 0;
 
272
//  guint32 *           uint_ip4_wins  = NULL;
 
273
  guint32               uint_ip4_wins1    = 0;
 
274
  guint32               uint_ip4_wins2    = 0;
 
275
  guint32               uint_ip4_wins_len = 0;
 
276
  guint32               uint_ip4_address  = 0;
 
277
  guint32               uint_ip4_ptp_address  = 0;
 
278
  guint32               uint_ip4_netmask  = 0xFFFFFFFF; /* Default mask of 255.255.255.255 */
 
279
//  guint32 i=0;
 
280
 
 
281
 
 
282
  g_return_if_fail (con != NULL);
 
283
  if (ipcp_gotoptions[ifunit].ouraddr==0) {
 
284
    info ("nm-pppd-plugin: didn't receive an Internal IP4 Address from ppp.");
 
285
    send_config_error (con, "IP4 Address");
 
286
    return;
 
287
  }
 
288
  uint_ip4_address=ipcp_gotoptions[ifunit].ouraddr;
 
289
  
 
290
  if (!(message = dbus_message_new_method_call (NM_DBUS_SERVICE_PPP_STARTER, NM_DBUS_PATH_PPP_STARTER, NM_DBUS_INTERFACE_PPP_STARTER, "signalIP4Config")))
 
291
    {
 
292
      nm_warning ("send_config_error(): Couldn't allocate the dbus message");
 
293
      return;
 
294
    }
 
295
 
 
296
  if (ipcp_gotoptions[ifunit].dnsaddr) {
 
297
    if (ipcp_gotoptions[ifunit].dnsaddr[0]!=0) {
 
298
      uint_ip4_dns_len++; 
 
299
      uint_ip4_dns1=ipcp_gotoptions[ifunit].dnsaddr[0];
 
300
      if (ipcp_gotoptions[ifunit].dnsaddr[1]!=0) {
 
301
        uint_ip4_dns_len++;
 
302
        uint_ip4_dns2=ipcp_gotoptions[ifunit].dnsaddr[1];
 
303
      }  
 
304
    }
 
305
  }
 
306
 
 
307
  if (ipcp_gotoptions[ifunit].winsaddr) {
 
308
    if (ipcp_gotoptions[ifunit].winsaddr[0]!=0) {
 
309
      uint_ip4_wins_len++; 
 
310
      uint_ip4_wins1=ipcp_gotoptions[ifunit].winsaddr[0];
 
311
      if (ipcp_gotoptions[ifunit].winsaddr[1]!=0) {
 
312
        uint_ip4_wins_len++;
 
313
        uint_ip4_wins2=ipcp_gotoptions[ifunit].winsaddr[1];
 
314
      }
 
315
    }
 
316
  }
 
317
 
 
318
  if (ifname==NULL) {
 
319
    info ("nm-pppd-plugin: didn't receive a tunnel device name.");
 
320
    send_config_error (con, "IP4 Address");
 
321
  }
 
322
  str_ifname = g_strdup(ifname);
 
323
 
 
324
  dbus_message_append_args (message, 
 
325
                            DBUS_TYPE_STRING, &str_ifname,
 
326
                            DBUS_TYPE_UINT32, &uint_ip4_address,
 
327
                            DBUS_TYPE_UINT32, &uint_ip4_ptp_address,
 
328
                            DBUS_TYPE_UINT32, &uint_ip4_netmask,
 
329
// Array workaround
 
330
                DBUS_TYPE_UINT32, &uint_ip4_dns1,
 
331
                            DBUS_TYPE_UINT32, &uint_ip4_dns2,
 
332
                            DBUS_TYPE_UINT32, &uint_ip4_dns_len,
 
333
                            DBUS_TYPE_UINT32, &uint_ip4_wins1,
 
334
                            DBUS_TYPE_UINT32, &uint_ip4_wins2,
 
335
                            DBUS_TYPE_UINT32, &uint_ip4_wins_len, 
 
336
                            DBUS_TYPE_INVALID);
 
337
 
 
338
  if (!dbus_connection_send (con, message, NULL)) {
 
339
    info ("nm_ip_up(): could not send dbus message");
 
340
    dbus_message_unref (message);
 
341
    g_free(str_ifname);
 
342
    return;
 
343
  }
 
344
  
 
345
  g_free(str_ifname);
 
346
  dbus_message_unref (message);
 
347
  return;
 
348
}
 
349
 
 
350
 
 
351
/*
 
352
 * send_config_error
 
353
 *
 
354
 * Notify nm-ppp-starter of a config error from pppd.
 
355
 *
 
356
*/
 
357
void send_config_error (DBusConnection *con, const char *item)
 
358
{
 
359
  DBusMessage           *message;
 
360
 
 
361
  g_return_if_fail (con != NULL);
 
362
  g_return_if_fail (item != NULL);
 
363
 
 
364
  if (!(message = dbus_message_new_method_call (NM_DBUS_SERVICE_PPP_STARTER, NM_DBUS_PATH_PPP_STARTER, NM_DBUS_INTERFACE_PPP_STARTER, "signalConfigError")))
 
365
    {
 
366
      nm_warning ("send_config_error(): Couldn't allocate the dbus message");
 
367
      return;
 
368
    }
 
369
 
 
370
  dbus_message_append_args (message, DBUS_TYPE_STRING, &item, DBUS_TYPE_INVALID);
 
371
  if (!dbus_connection_send (con, message, NULL))
 
372
    nm_warning ("send_config_error(): could not send dbus message");
 
373
  
 
374
  dbus_message_unref (message);
 
375
}
 
376
 
 
377
 
 
378
/*
 
379
 * nm_notify_pid
 
380
 *
 
381
 * Let the pppd starter service know our PID
 
382
 * so that pppd may be killed later.
 
383
 *
 
384
 */
 
385
void nm_notify_pid (NmPPPData *data)
 
386
{
 
387
  DBusConnection *con;
 
388
  DBusMessage *message = NULL;
 
389
 
 
390
  if (!nm_dbus_prepare_connection(data)) 
 
391
      return;
 
392
   
 
393
  con = data->con;
 
394
  if (!(message = dbus_message_new_method_call (NM_DBUS_SERVICE_PPP_STARTER, NM_DBUS_PATH_PPP_STARTER, NM_DBUS_INTERFACE_PPP_STARTER, "notifyPID")))
 
395
  {
 
396
    nm_warning ("nm-pppd-plugin: Couldn't allocate the notifyPID dbus message");
 
397
    return;
 
398
  }
 
399
 
 
400
  dbus_message_append_args (message, 
 
401
        DBUS_TYPE_UINT32, &(data->pppd_pid),
 
402
        DBUS_TYPE_INVALID);
 
403
 
 
404
  if (!dbus_connection_send (con, message, NULL)) {
 
405
    info ("nm_ip_up(): could not send dbus message");
 
406
    dbus_message_unref (message);
 
407
    return;
 
408
  }
 
409
 
 
410
//  nm_warning("Sent notify message: %d",data->pppd_pid);
 
411
  dbus_message_unref (message);
 
412
}
 
413
/*
 
414
 * nm_get_auth_items
 
415
 *
 
416
 * Request credentials from PPP_STARTER service.
 
417
 *
 
418
 */
 
419
gboolean nm_get_auth_items (NmPPPData *data)
 
420
{
 
421
  DBusConnection *con;
 
422
  int num_auth_items = -1;
 
423
  char *auth_items[3] = { NULL, NULL, NULL };
 
424
//  char **auth_items = NULL;
 
425
  DBusMessage *message = NULL;
 
426
  DBusMessage *reply = NULL;
 
427
 
 
428
  if (!nm_dbus_prepare_connection(data)) 
 
429
      return FALSE;
 
430
   
 
431
  con = data->con;
 
432
 
 
433
  g_return_val_if_fail (con != NULL,FALSE);
 
434
  if (!(message = dbus_message_new_method_call (NM_DBUS_SERVICE_PPP_STARTER, NM_DBUS_PATH_PPP_STARTER, NM_DBUS_INTERFACE_PPP_STARTER, "getAuthInfo")))
 
435
  {
 
436
    nm_warning("nm-pppd-plugin: failed to create getAuthInfo message.");
 
437
    return FALSE;
 
438
  }
 
439
 
 
440
  reply = dbus_connection_send_with_reply_and_block (con, message, -1, NULL);
 
441
  dbus_message_unref (message);
 
442
  if (!reply)
 
443
    {
 
444
      info("nm-pppd-plugin: no reply to getAuthInfo message.");
 
445
      return FALSE;
 
446
    }
 
447
 
 
448
  if (!(dbus_message_get_args (reply, NULL, 
 
449
              DBUS_TYPE_STRING, &(auth_items[0]),
 
450
              DBUS_TYPE_STRING, &(auth_items[1]),
 
451
              DBUS_TYPE_STRING, &(auth_items[2]),
 
452
//              DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &auth_items, &num_auth_items, 
 
453
              DBUS_TYPE_INVALID)))
 
454
  {
 
455
    dbus_message_unref (reply);
 
456
    return FALSE;
 
457
  }
 
458
  num_auth_items=3;
 
459
 
 
460
  if (!nm_store_auth_info (data, auth_items, num_auth_items))
 
461
  {
 
462
    //dbus_free_string_array (auth_items);
 
463
    dbus_message_unref (reply);
 
464
    return FALSE;
 
465
  }
 
466
 
 
467
  //dbus_free_string_array (auth_items);
 
468
  dbus_message_unref (reply);
 
469
  return TRUE;
 
470
}
 
471
 
 
472
/*
 
473
 * nm_store_auth_info
 
474
 *
 
475
 * Decode and temporarily store the authentication info provided.
 
476
 *
 
477
 */
 
478
gboolean nm_store_auth_info (NmPPPData *data, char **auth_items, int num_auth_items)
 
479
{
 
480
//  int i=0;
 
481
  g_return_val_if_fail (auth_items != NULL, FALSE);
 
482
  g_return_val_if_fail (num_auth_items >= 1, FALSE);
 
483
 
 
484
  nm_warning ("PPPD will authenticate using '%s'.", auth_items[0]);
 
485
  
 
486
  if (strcmp ("CHAP", auth_items[0]) == 0) {
 
487
    g_return_val_if_fail (num_auth_items >= 3, FALSE);
 
488
    if (data->auth_type!=NULL) g_free(data->auth_type);
 
489
    if (data->username!=NULL) g_free(data->username);
 
490
    if (data->password!=NULL) g_free(data->password);
 
491
    data->auth_type=g_strdup(auth_items[0]);
 
492
    data->username=g_strdup(auth_items[1]);
 
493
    data->password=g_strdup(auth_items[2]);
 
494
  } else if (strcmp ("NONE", auth_items[0]) == 0) {
 
495
    if (data->auth_type!=NULL) g_free(data->auth_type);
 
496
    if (data->username!=NULL) g_free(data->username);
 
497
    if (data->password!=NULL) g_free(data->password);
 
498
    data->auth_type=g_strdup(auth_items[0]);
 
499
  } else {
 
500
          nm_warning ("PPPD authentication type '%s' is not allowed.", auth_items[0]);
 
501
      return FALSE;
 
502
  }
 
503
 
 
504
  data->got_auth_info=TRUE;
 
505
  return TRUE;
 
506
}
 
507
 
 
508
int plugin_init()
 
509
{
 
510
//    DBusConnection *  con = NULL;
 
511
//    DBusMessage *     message = NULL;
 
512
//    DBusError         error;
 
513
 
 
514
//    g_type_init ();
 
515
//    if (!g_thread_supported ())
 
516
//      g_thread_init (NULL);
 
517
    
 
518
//    dbus_error_init (&error);
 
519
//    con = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
 
520
//    if ((con == NULL) || dbus_error_is_set (&error))
 
521
//      {
 
522
//        dbus_error_free (&error);
 
523
//        info("Could not get the system bus.  Make sure the message bus daemon is running?");
 
524
//        return -1;
 
525
//      }
 
526
//    dbus_connection_set_exit_on_disconnect (con, FALSE);
 
527
//
 
528
//
 
529
//    dbus_error_free (&error);
 
530
 
 
531
//    add_options(ppp_options);
 
532
 
 
533
    chap_check_hook = nm_chap_check_hook;
 
534
    chap_passwd_hook = nm_chap_passwd_hook;
 
535
 
 
536
    add_notifier(&ip_down_notifier, nm_ip_down, (void *) &plugin_data);
 
537
    add_notifier(&ip_up_notifier, nm_ip_up, (void *) &plugin_data);
 
538
    add_notifier(&exitnotify, nm_exit_notify, (void *) &plugin_data);
 
539
 
 
540
    info("nm-pppd-plugin: plugin initialized.");
 
541
    return 0;
 
542
}
 
543
 
 
544