Coverage Report

Created: 2026-08-13 09:19

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/net-snmp/snmplib/snmp_parse_args.c
Line
Count
Source
1
/*
2
 * snmp_parse_args.c
3
 */
4
/* Portions of this file are subject to the following copyright(s).  See
5
 * the Net-SNMP's COPYING file for more details and other copyrights
6
 * that may apply:
7
 */
8
/*
9
 * Portions of this file are copyrighted by:
10
 * Copyright @ 2003 Sun Microsystems, Inc. All rights reserved.
11
 * Use is subject to license terms specified in the COPYING file
12
 * distributed with the Net-SNMP package.
13
 *
14
 * Portions of this file are copyrighted by:
15
 * Copyright (c) 2016 VMware, Inc. All rights reserved.
16
 * Use is subject to license terms specified in the COPYING file
17
 * distributed with the Net-SNMP package.
18
 */
19
20
#include <net-snmp/net-snmp-config.h>
21
#include <errno.h>
22
23
#ifdef HAVE_STDLIB_H
24
#include <stdlib.h>
25
#endif
26
#ifdef HAVE_UNISTD_H
27
#include <unistd.h>
28
#endif
29
#ifdef HAVE_STRING_H
30
#include <string.h>
31
#else
32
#include <strings.h>
33
#endif
34
#include <sys/types.h>
35
#include <stdio.h>
36
#ifdef HAVE_UNISTD_H
37
#include <unistd.h>
38
#endif
39
#include <ctype.h>
40
#ifdef HAVE_NETINET_IN_H
41
#include <netinet/in.h>
42
#endif
43
#ifdef TIME_WITH_SYS_TIME
44
# include <sys/time.h>
45
# include <time.h>
46
#else
47
# ifdef HAVE_SYS_TIME_H
48
#  include <sys/time.h>
49
# else
50
#  include <time.h>
51
# endif
52
#endif
53
#ifdef HAVE_SYS_SELECT_H
54
#include <sys/select.h>
55
#endif
56
#ifdef HAVE_NETDB_H
57
#include <netdb.h>
58
#endif
59
#ifdef HAVE_ARPA_INET_H
60
#include <arpa/inet.h>
61
#endif
62
63
#include <net-snmp/net-snmp-includes.h>
64
#include <net-snmp/types.h>
65
#include <net-snmp/output_api.h>
66
#include <net-snmp/config_api.h>
67
#include <net-snmp/library/snmpv3.h>
68
#include <net-snmp/library/snmp_parse_args.h>   /* for "internal" definitions */
69
#include <net-snmp/utilities.h>
70
71
#include <net-snmp/library/snmp_api.h>
72
#include <net-snmp/library/snmp_client.h>
73
#include <net-snmp/library/mib.h>
74
#include <net-snmp/library/scapi.h>
75
#include <net-snmp/library/keytools.h>
76
77
#include <net-snmp/version.h>
78
#include <net-snmp/library/parse.h>
79
#include <net-snmp/library/snmpv3.h>
80
#include <net-snmp/library/transform_oids.h>
81
82
void
83
snmp_parse_args_usage(FILE * outf)
84
0
{
85
0
    fprintf(outf, "[OPTIONS] AGENT");
86
0
}
87
88
void
89
snmp_parse_args_descriptions(FILE * outf)
90
0
{
91
0
    fprintf(outf, "  Version:  %s\n", netsnmp_get_version());
92
0
    fprintf(outf, "  Web:      http://www.net-snmp.org/\n");
93
0
    fprintf(outf,
94
0
            "  Email:    net-snmp-coders@lists.sourceforge.net\n\nOPTIONS:\n");
95
0
    fprintf(outf, "  -h, --help\t\tdisplay this help message\n");
96
0
    fprintf(outf,
97
0
            "  -H\t\t\tdisplay configuration file directives understood\n");
98
0
    fprintf(outf, "  -v 1|2c|3\t\tspecifies SNMP version to use\n");
99
0
    fprintf(outf, "  -V, --version\t\tdisplay package version number\n");
100
0
#if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
101
0
    fprintf(outf, "SNMP Version 1 or 2c specific\n");
102
0
    fprintf(outf, "  -c COMMUNITY\t\tset the community string\n");
103
0
#endif /* support for community based SNMP */
104
0
    fprintf(outf, "SNMP Version 3 specific\n");
105
0
    fprintf(outf,
106
0
            "  -a PROTOCOL\t\tset authentication protocol (MD5|SHA|SHA-224|SHA-256|SHA-384|SHA-512)\n");
107
0
    fprintf(outf,
108
0
            "  -A PASSPHRASE\t\tset authentication protocol pass phrase\n");
109
0
    fprintf(outf,
110
0
            "  -e ENGINE-ID\t\tset security engine ID (e.g. 800000020109840301)\n");
111
0
    fprintf(outf,
112
0
            "  -E ENGINE-ID\t\tset context engine ID (e.g. 800000020109840301)\n");
113
0
    fprintf(outf,
114
0
            "  -l LEVEL\t\tset security level (noAuthNoPriv|authNoPriv|authPriv)\n");
115
0
    fprintf(outf, "  -n CONTEXT\t\tset context name (e.g. bridge1)\n");
116
0
    fprintf(outf, "  -u USER-NAME\t\tset security name (e.g. bert)\n");
117
0
#ifdef HAVE_AES
118
0
    fprintf(outf, "  -x PROTOCOL\t\tset privacy protocol (DES|AES"
119
0
#ifdef NETSNMP_DRAFT_BLUMENTHAL_AES_04
120
0
            "|AES-192|AES-256"
121
0
#endif
122
0
            ")\n");
123
#else
124
    fprintf(outf, "  -x PROTOCOL\t\tset privacy protocol (DES)\n");
125
#endif
126
0
    fprintf(outf, "  -X PASSPHRASE\t\tset privacy protocol pass phrase\n");
127
0
    fprintf(outf,
128
0
            "  -Z BOOTS,TIME\t\tset destination engine boots/time\n");
129
0
    fprintf(outf, "General communication options\n");
130
0
    fprintf(outf, "  -r RETRIES\t\tset the number of retries\n");
131
0
    fprintf(outf,
132
0
            "  -t TIMEOUT\t\tset the request timeout (in seconds)\n");
133
0
    fprintf(outf, "Debugging\n");
134
0
    fprintf(outf, "  -d\t\t\tdump input/output packets in hexadecimal\n");
135
0
#ifndef NETSNMP_DISABLE_DEBUGGING
136
0
    fprintf(outf,
137
0
            "  -D[TOKEN[,...]]\tturn on debugging output for the specified TOKENs\n\t\t\t   (ALL gives extremely verbose debugging output)\n");
138
0
#endif
139
0
    fprintf(outf, "General options\n");
140
0
    fprintf(outf,
141
0
            "  -m MIB[" ENV_SEPARATOR "...]\t\tload given list of MIBs (ALL loads everything)\n");
142
0
    fprintf(outf,
143
0
            "  -M DIR[" ENV_SEPARATOR "...]\t\tlook in given list of directories for MIBs\n");
144
0
#ifndef NETSNMP_DISABLE_MIB_LOADING
145
0
    fprintf(outf,
146
0
            "    (default: %s)\n", netsnmp_get_mib_directory());
147
0
    fprintf(outf,
148
0
            "  -P MIBOPTS\t\tToggle various defaults controlling MIB parsing:\n");
149
0
    snmp_mib_toggle_options_usage("\t\t\t  ", outf);
150
0
#endif
151
0
    fprintf(outf,
152
0
            "  -O OUTOPTS\t\tToggle various defaults controlling output display:\n");
153
0
    snmp_out_toggle_options_usage("\t\t\t  ", outf);
154
0
    fprintf(outf,
155
0
            "  -I INOPTS\t\tToggle various defaults controlling input parsing:\n");
156
0
    snmp_in_toggle_options_usage("\t\t\t  ", outf);
157
0
    fprintf(outf,
158
0
            "  -L LOGOPTS\t\tToggle various defaults controlling logging:\n");
159
0
    snmp_log_options_usage("\t\t\t  ", outf);
160
0
    fflush(outf);
161
0
}
162
163
#define BUF_SIZE 512
164
165
void
166
handle_long_opt(const char *myoptarg)
167
9.31k
{
168
9.31k
    char           *cp, *cp2;
169
    /*
170
     * else it's a long option, so process it like name=value 
171
     */
172
9.31k
    cp = (char *)malloc(strlen(myoptarg) + 3);
173
9.31k
    if (!cp)
174
0
        return;
175
9.31k
    strcpy(cp, myoptarg);
176
9.31k
    cp2 = strchr(cp, '=');
177
9.31k
    if (!cp2 && !strchr(cp, ' ')) {
178
        /*
179
         * well, they didn't specify an argument as far as we
180
         * can tell.  Give them a '1' as the argument (which
181
         * works for boolean tokens and a few others) and let
182
         * them suffer from there if it's not what they
183
         * wanted 
184
         */
185
4.11k
        strcat(cp, " 1");
186
5.19k
    } else {
187
        /*
188
         * replace the '=' with a ' ' 
189
         */
190
5.19k
        if (cp2)
191
1.23k
            *cp2 = ' ';
192
5.19k
    }
193
9.31k
    netsnmp_config(cp);
194
9.31k
    free(cp);
195
9.31k
}
196
197
int
198
netsnmp_parse_args(int argc,
199
                   char **argv,
200
                   netsnmp_session * session, const char *localOpts,
201
                   void (*proc) (int, char *const *, int),
202
                   int flags)
203
5.00k
{
204
5.00k
    int             arg, ret, sp = 0;
205
5.00k
    const char     *cp;
206
5.00k
    char           *Apsz = NULL;
207
5.00k
    char           *Xpsz = NULL;
208
5.00k
    char           *Cpsz = NULL;
209
5.00k
    char            Opts[BUF_SIZE];
210
5.00k
    int             zero_sensitive = !( flags & NETSNMP_PARSE_ARGS_NOZERO );
211
5.00k
    char           *backup_NETSNMP_DS_LIB_OUTPUT_PRECISION = NULL;
212
213
    /*
214
     * initialize session to default values 
215
     */
216
5.00k
    snmp_sess_init(session);
217
5.00k
    strcpy(Opts, "Y:VhHm:M:O:I:P:D:dv:r:t:c:Z:e:E:n:u:l:x:X:a:A:p:T:-:3:L:s:");
218
5.00k
    if (localOpts) {
219
5.00k
        if (strlen(localOpts) + strlen(Opts) >= sizeof(Opts)) {
220
0
            snmp_log(LOG_ERR, "Too many localOpts in snmp_parse_args()\n");
221
0
            return -1;
222
0
        }
223
5.00k
        strcat(Opts, localOpts);
224
5.00k
    }
225
226
    /*
227
     * get the options 
228
     */
229
5.00k
    DEBUGMSGTL(("snmp_parse_args", "starting: %d/%d\n", optind, argc));
230
41.5k
    for (arg = 0; arg < argc; arg++) {
231
36.5k
        DEBUGMSGTL(("snmp_parse_args", " arg %d = %s\n", arg, argv[arg]));
232
36.5k
    }
233
234
5.00k
#ifdef __linux__
235
    /*
236
     * glibc only resets the internal getopt() state if optind is set to zero.
237
     */
238
5.00k
    optind = 0;
239
#else
240
    optind = 1;
241
#endif
242
23.1k
    while (optind < argc && (arg = getopt(argc, argv, Opts)) != EOF) {
243
19.0k
        DEBUGMSGTL(("snmp_parse_args", "handling (#%d): %c (optarg %s) (sp %d)\n",
244
19.0k
                    optind, arg, optarg, sp));
245
19.0k
        switch (arg) {
246
9.31k
        case '-':
247
9.31k
            if (strcasecmp(optarg, "help") == 0) {
248
2
                ret = NETSNMP_PARSE_ARGS_ERROR_USAGE;
249
2
                goto out;
250
2
            }
251
9.31k
            if (strcasecmp(optarg, "version") == 0) {
252
1
                fprintf(stderr,"NET-SNMP version: %s\n",netsnmp_get_version());
253
1
                ret = NETSNMP_PARSE_ARGS_SUCCESS_EXIT;
254
1
                goto out;
255
1
            }
256
257
9.31k
            handle_long_opt(optarg);
258
9.31k
            break;
259
260
1
        case 'V':
261
1
            fprintf(stderr, "NET-SNMP version: %s\n", netsnmp_get_version());
262
1
            ret = NETSNMP_PARSE_ARGS_SUCCESS_EXIT;
263
1
            goto out;
264
265
1
        case 'h':
266
1
            ret = NETSNMP_PARSE_ARGS_ERROR_USAGE;
267
1
            goto out;
268
269
14
        case 'H':
270
14
            init_snmp(NETSNMP_APPLICATION_CONFIG_TYPE);
271
14
            fprintf(stderr, "Configuration directives understood:\n");
272
14
            read_config_print_usage("  ");
273
14
            ret = NETSNMP_PARSE_ARGS_SUCCESS_EXIT;
274
14
            goto out;
275
276
41
        case 'Y':
277
41
            netsnmp_config_remember(optarg);
278
41
            break;
279
280
0
#ifndef NETSNMP_DISABLE_MIB_LOADING
281
83
        case 'm':
282
83
            setenv("MIBS", optarg, 1);
283
83
            break;
284
285
211
        case 'M':
286
211
            netsnmp_get_mib_directory(); /* prepare the default directories */
287
211
            netsnmp_set_mib_directory(optarg);
288
211
            break;
289
0
#endif /* NETSNMP_DISABLE_MIB_LOADING */
290
291
195
        case 'O':
292
195
            cp = snmp_out_options(optarg, argc, argv);
293
195
            if (cp != NULL) {
294
63
                fprintf(stderr, "Unknown output option passed to -O: %c.\n", 
295
63
      *cp);
296
63
                ret = NETSNMP_PARSE_ARGS_ERROR_USAGE;
297
63
                goto out;
298
63
            }
299
132
            break;
300
301
265
        case 'I':
302
265
            cp = snmp_in_options(optarg, argc, argv);
303
265
            if (cp != NULL) {
304
22
                fprintf(stderr, "Unknown input option passed to -I: %c.\n",
305
22
      *cp);
306
22
                ret = NETSNMP_PARSE_ARGS_ERROR_USAGE;
307
22
                goto out;
308
22
            }
309
243
            break;
310
311
243
#ifndef NETSNMP_DISABLE_MIB_LOADING
312
243
        case 'P':
313
54
            cp = snmp_mib_toggle_options(optarg);
314
54
            if (cp != NULL) {
315
28
                fprintf(stderr,
316
28
                        "Unknown parsing option passed to -P: %c.\n", *cp);
317
28
                ret = NETSNMP_PARSE_ARGS_ERROR_USAGE;
318
28
                goto out;
319
28
            }
320
26
            break;
321
26
#endif /* NETSNMP_DISABLE_MIB_LOADING */
322
323
352
        case 'D':
324
#ifdef NETSNMP_NO_DEBUGGING
325
            fprintf(stderr, "Debug not configured in\n");
326
            ret = NETSNMP_PARSE_ARGS_ERROR_USAGE;
327
            goto out;
328
#else
329
352
            debug_register_tokens(optarg);
330
352
            snmp_set_do_debugging(1);
331
352
#endif
332
352
            break;
333
334
3.17k
        case 'd':
335
3.17k
            netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, 
336
3.17k
           NETSNMP_DS_LIB_DUMP_PACKET, 1);
337
3.17k
            break;
338
339
83
        case 's':
340
83
            free(session->localname);
341
83
            session->localname = strdup(optarg);
342
83
            break;
343
344
97
        case 'v':
345
97
            session->version = -1;
346
97
#ifndef NETSNMP_DISABLE_SNMPV1
347
97
            if (!strcmp(optarg, "1")) {
348
20
                session->version = SNMP_VERSION_1;
349
20
            }
350
97
#endif
351
97
#ifndef NETSNMP_DISABLE_SNMPV2C
352
97
            if (!strcasecmp(optarg, "2c")) {
353
12
                session->version = SNMP_VERSION_2c;
354
12
            }
355
97
#endif
356
97
            if (!strcasecmp(optarg, "3")) {
357
38
                session->version = SNMP_VERSION_3;
358
38
            }
359
97
            if (session->version == -1) {
360
27
                fprintf(stderr,
361
27
                        "Invalid version specified after -v flag: %s\n",
362
27
                        optarg);
363
27
                ret = NETSNMP_PARSE_ARGS_ERROR_USAGE;
364
27
                goto out;
365
27
            }
366
70
            break;
367
368
70
        case 'p':
369
1
            fprintf(stderr, "Warning: -p option is no longer used - ");
370
1
            fprintf(stderr, "specify the remote host as HOST:PORT\n");
371
1
            ret = NETSNMP_PARSE_ARGS_ERROR_USAGE;
372
1
            goto out;
373
374
106
        case 'T':
375
106
        {
376
106
            char leftside[SNMP_MAXBUF_MEDIUM], rightside[SNMP_MAXBUF_MEDIUM];
377
106
            char *tmpcp, *tmpopt;
378
            
379
            /* ensure we have a proper argument */
380
106
            tmpopt = strdup(optarg);
381
106
            tmpcp = strchr(tmpopt, '=');
382
106
            if (!tmpcp) {
383
2
                fprintf(stderr, "-T expects a NAME=VALUE pair.\n");
384
2
                free(tmpopt);
385
2
                ret = NETSNMP_PARSE_ARGS_ERROR_USAGE;
386
2
                goto out;
387
2
            }
388
104
            *tmpcp++ = '\0';
389
390
            /* create the transport config container if this is the first */
391
104
            if (!session->transport_configuration) {
392
15
                netsnmp_container_init_list();
393
15
                session->transport_configuration =
394
15
                    netsnmp_container_find("transport_configuration:fifo");
395
15
                if (!session->transport_configuration) {
396
0
                    fprintf(stderr, "failed to initialize the transport configuration container\n");
397
0
                    free(tmpopt);
398
0
                    ret = NETSNMP_PARSE_ARGS_ERROR;
399
0
                    goto out;
400
0
                }
401
402
15
                session->transport_configuration->compare =
403
15
                    netsnmp_transport_config_compare;
404
15
            }
405
406
            /* set the config */
407
104
            strlcpy(leftside, tmpopt, sizeof(leftside));
408
104
            strlcpy(rightside, tmpcp, sizeof(rightside));
409
410
104
            CONTAINER_INSERT(session->transport_configuration,
411
104
                             netsnmp_transport_create_config(leftside,
412
104
                                                             rightside));
413
104
            free(tmpopt);
414
104
        }
415
0
        break;
416
            
417
130
        case 't':
418
130
            session->timeout = (long)(atof(optarg) * 1000000L);
419
130
            if (session->timeout <= 0) {
420
66
                fprintf(stderr, "Invalid timeout in seconds after -t flag.\n");
421
66
                ret = NETSNMP_PARSE_ARGS_ERROR_USAGE;
422
66
                goto out;
423
66
            }
424
64
            break;
425
426
114
        case 'r':
427
114
            session->retries = atoi(optarg);
428
114
            if (session->retries < 0 || !isdigit((unsigned char)(optarg[0]))) {
429
41
                fprintf(stderr, "Invalid number of retries after -r flag.\n");
430
41
                ret = NETSNMP_PARSE_ARGS_ERROR_USAGE;
431
41
                goto out;
432
41
            }
433
73
            break;
434
435
73
        case 'c':
436
61
      if (zero_sensitive) {
437
61
                SNMP_FREE(Cpsz); /* free any previous value */
438
61
    if ((Cpsz = strdup(optarg)) != NULL) {
439
61
        memset(optarg, '\0', strlen(optarg));
440
61
    } else {
441
0
        fprintf(stderr, "malloc failure processing -c flag.\n");
442
0
        ret = NETSNMP_PARSE_ARGS_ERROR;
443
0
                    goto out;
444
0
    }
445
61
      } else {
446
0
    Cpsz = strdup(optarg);
447
0
      }
448
61
            break;
449
450
108
        case '3':
451
108
            if (snmpv3_parse_args(optarg, session, &Apsz, &Xpsz, argc, argv,
452
108
                                  flags) < 0){
453
24
                ret = NETSNMP_PARSE_ARGS_ERROR_USAGE;
454
24
                goto out;
455
24
            }
456
84
            break;
457
458
3.23k
        case 'L':
459
3.23k
            if (snmp_log_options(optarg, argc, argv) < 0) {
460
73
                ret = NETSNMP_PARSE_ARGS_ERROR_USAGE;
461
73
                goto out;
462
73
            }
463
3.16k
            break;
464
465
3.16k
#define SNMPV3_CMD_OPTIONS
466
3.16k
#ifdef  SNMPV3_CMD_OPTIONS
467
3.16k
        case 'Z':
468
136
        case 'e':
469
180
        case 'E':
470
263
        case 'n':
471
783
        case 'l':
472
859
        case 'u':
473
859
#ifdef NETSNMP_SECMOD_USM
474
942
        case 'a':
475
1.09k
        case 'x':
476
1.19k
        case 'A':
477
1.32k
        case 'X':
478
1.32k
#endif             /* NETSNMP_SECMOD_USM */
479
1.32k
            if (snmpv3_parse_arg(arg, optarg, session, &Apsz, &Xpsz, argc,
480
1.32k
                                 argv, flags) < 0){
481
444
                ret = NETSNMP_PARSE_ARGS_ERROR_USAGE;
482
444
                goto out;
483
444
            }
484
879
            break;
485
879
#endif                          /* SNMPV3_CMD_OPTIONS */
486
487
879
        case '?':
488
63
        case ':':
489
63
            ret = NETSNMP_PARSE_ARGS_ERROR_USAGE;
490
63
            goto out;
491
492
0
        default:
493
0
            proc(argc, argv, arg);
494
0
            break;
495
19.0k
        }
496
19.0k
    }
497
4.12k
    DEBUGMSGTL(("snmp_parse_args", "finished: %d/%d\n", optind, argc));
498
    
499
    /*
500
     * save command line parameters which should have precedence above config file settings
501
     *    (There ought to be a more scalable approach than this....)
502
     */
503
4.12k
    if (netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OUTPUT_PRECISION)) {
504
3.31k
        backup_NETSNMP_DS_LIB_OUTPUT_PRECISION = 
505
3.31k
            strdup(netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OUTPUT_PRECISION));
506
3.31k
    }
507
508
    /*
509
     * read in MIB database and initialize the snmp library, read the config file
510
     */
511
4.12k
    init_snmp(NETSNMP_APPLICATION_CONFIG_TYPE);
512
513
    /*
514
     * restore command line parameters which should have precedence above config file settings
515
     */
516
4.12k
    if(backup_NETSNMP_DS_LIB_OUTPUT_PRECISION) {
517
3.31k
        netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OUTPUT_PRECISION, backup_NETSNMP_DS_LIB_OUTPUT_PRECISION);
518
3.31k
        free(backup_NETSNMP_DS_LIB_OUTPUT_PRECISION);
519
3.31k
    }
520
521
    /*
522
     * session default version 
523
     */
524
4.12k
    if (session->version == SNMP_DEFAULT_VERSION) {
525
        /*
526
         * run time default version 
527
         */
528
4.11k
        session->version = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 
529
4.11k
                NETSNMP_DS_LIB_SNMPVERSION);
530
531
        /*
532
         * compile time default version 
533
         */
534
4.11k
        if (!session->version) {
535
129
            switch (NETSNMP_DEFAULT_SNMP_VERSION) {
536
0
#ifndef NETSNMP_DISABLE_SNMPV1
537
0
            case 1:
538
0
                session->version = SNMP_VERSION_1;
539
0
                break;
540
0
#endif
541
542
0
#ifndef NETSNMP_DISABLE_SNMPV2C
543
129
            case 2:
544
129
                session->version = SNMP_VERSION_2c;
545
129
                break;
546
0
#endif
547
548
0
            case 3:
549
0
                session->version = SNMP_VERSION_3;
550
0
                break;
551
552
0
            default:
553
0
                snmp_log(LOG_ERR, "Can't determine a valid SNMP version for the session\n");
554
0
                return(NETSNMP_PARSE_ARGS_ERROR);
555
129
            }
556
3.98k
        } else {
557
3.98k
#ifndef NETSNMP_DISABLE_SNMPV1
558
3.98k
            if (session->version == NETSNMP_DS_SNMP_VERSION_1)  /* bogus value.  version 1 actually = 0 */
559
956
                session->version = SNMP_VERSION_1;
560
3.98k
#endif
561
3.98k
        }
562
4.11k
    }
563
564
4.12k
#ifdef NETSNMP_SECMOD_USM
565
    /* XXX: this should ideally be moved to snmpusm.c somehow */
566
567
    /*
568
     * make master key from pass phrases 
569
     */
570
4.12k
    if (Apsz) {
571
31
        session->securityAuthKeyLen = USM_AUTH_KU_LEN;
572
31
        if (session->securityAuthProto == NULL) {
573
            /*
574
             * get .conf set default 
575
             */
576
19
            const oid      *def =
577
19
                get_default_authtype(&session->securityAuthProtoLen);
578
19
            session->securityAuthProto =
579
19
                snmp_duplicate_objid(def, session->securityAuthProtoLen);
580
19
        }
581
31
        if (session->securityAuthProto == NULL) {
582
0
            session->securityAuthProto =
583
0
                snmp_duplicate_objid(SNMP_DEFAULT_AUTH_PROTO,
584
0
                                     SNMP_DEFAULT_AUTH_PROTOLEN);
585
0
            session->securityAuthProtoLen = SNMP_DEFAULT_AUTH_PROTOLEN;
586
0
        }
587
31
        if (generate_Ku(session->securityAuthProto,
588
31
                        session->securityAuthProtoLen,
589
31
                        (u_char *) Apsz, strlen(Apsz),
590
31
                        session->securityAuthKey,
591
31
                        &session->securityAuthKeyLen) != SNMPERR_SUCCESS) {
592
13
            snmp_perror(argv[0]);
593
13
            fprintf(stderr,
594
13
                    "Error generating a key (Ku) from the supplied authentication pass phrase. \n");
595
13
            ret = NETSNMP_PARSE_ARGS_ERROR;
596
13
            goto out;
597
13
        }
598
18
        free(Apsz);
599
18
        Apsz = NULL;
600
18
    }
601
4.11k
    if (Xpsz) {
602
27
        session->securityPrivKeyLen = USM_PRIV_KU_LEN;
603
27
        if (session->securityPrivProto == NULL) {
604
            /*
605
             * get .conf set default 
606
             */
607
26
            const oid      *def =
608
26
                get_default_privtype(&session->securityPrivProtoLen);
609
26
            session->securityPrivProto =
610
26
                snmp_duplicate_objid(def, session->securityPrivProtoLen);
611
26
        }
612
27
        if (session->securityPrivProto == NULL) {
613
0
            session->securityPrivProto =
614
0
                snmp_duplicate_objid(SNMP_DEFAULT_PRIV_PROTO,
615
0
                                     SNMP_DEFAULT_PRIV_PROTOLEN);
616
0
            session->securityPrivProtoLen = SNMP_DEFAULT_PRIV_PROTOLEN;
617
0
        }
618
27
        if (generate_Ku(session->securityAuthProto,
619
27
                        session->securityAuthProtoLen,
620
27
                        (u_char *) Xpsz, strlen(Xpsz),
621
27
                        session->securityPrivKey,
622
27
                        &session->securityPrivKeyLen) != SNMPERR_SUCCESS) {
623
20
            snmp_perror(argv[0]);
624
20
            fprintf(stderr,
625
20
                    "Error generating a key (Ku) from the supplied privacy pass phrase. \n");
626
20
            ret = NETSNMP_PARSE_ARGS_ERROR;
627
20
            goto out;
628
20
        }
629
7
        free(Xpsz);
630
7
        Xpsz = NULL;
631
7
    }
632
4.09k
#endif /* NETSNMP_SECMOD_USM */
633
634
    /*
635
     * get the hostname 
636
     */
637
4.09k
    if (optind >= argc) {
638
3.44k
        fprintf(stderr, "No hostname specified.\n");
639
3.44k
        ret = NETSNMP_PARSE_ARGS_ERROR_USAGE;
640
3.44k
        goto out;
641
3.44k
    }
642
654
    session->peername = strdup(argv[optind++]); /* hostname */
643
654
    if (session->peername == NULL) {
644
0
        snmp_log(LOG_ERR, "strdup hostname failed - out of memory.\n");
645
0
        fprintf(stderr, "strdup hostname failed - out of memory.\n");
646
0
        ret = NETSNMP_PARSE_ARGS_ERROR;
647
0
        goto out;
648
0
    }
649
650
654
#if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
651
    /*
652
     * If v1 or v2c, check community has been set, either by a -c option above,
653
     * or via a default token somewhere.  
654
     * If neither, it will be taken from the incoming request PDU.
655
     */
656
657
#if defined(NETSNMP_DISABLE_SNMPV1)
658
    if (session->version == SNMP_VERSION_2c)
659
#else 
660
#if defined(NETSNMP_DISABLE_SNMPV2C)
661
    if (session->version == SNMP_VERSION_1)
662
#else
663
654
    if (session->version == SNMP_VERSION_1 ||
664
449
  session->version == SNMP_VERSION_2c)
665
439
#endif
666
439
#endif
667
439
    {
668
439
        if (Cpsz == NULL) {
669
435
            Cpsz = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 
670
435
           NETSNMP_DS_LIB_COMMUNITY);
671
435
      if (Cpsz == NULL) {
672
127
                if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
673
127
                                           NETSNMP_DS_LIB_IGNORE_NO_COMMUNITY)){
674
0
                    DEBUGMSGTL(("snmp_parse_args",
675
0
                                "ignoring that the community string is not present\n"));
676
0
                    session->community = NULL;
677
0
                    session->community_len = 0;
678
127
                } else {
679
127
                    fprintf(stderr, "No community name specified.\n");
680
127
                    ret = NETSNMP_PARSE_ARGS_ERROR_USAGE;
681
127
                    goto out;
682
127
                }
683
308
      } else {
684
308
                Cpsz = NULL;
685
308
            }
686
435
  } else {
687
4
            session->community = (unsigned char *)Cpsz;
688
4
            session->community_len = strlen(Cpsz);
689
4
            Cpsz = NULL;
690
4
        }
691
439
    }
692
527
#endif /* support for community based SNMP */
693
694
527
    ret = optind;
695
696
5.00k
out:
697
5.00k
    free(Apsz);
698
5.00k
    free(Xpsz);
699
5.00k
    free(Cpsz);
700
5.00k
    return ret;
701
527
}
702
703
int
704
snmp_parse_args(int argc,
705
                char **argv,
706
                netsnmp_session * session, const char *localOpts,
707
                void (*proc) (int, char *const *, int))
708
5.00k
{
709
5.00k
    return netsnmp_parse_args(argc, argv, session, localOpts, proc, 0);
710
5.00k
}