Annotation of embedaddon/mtr/packet/packet.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:     mtr  --  a network diagnostic tool
                      3:     Copyright (C) 2016  Matt Kimball
                      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 version 2 as
                      7:     published by the Free Software Foundation.
                      8: 
                      9:     This program 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
                     12:     GNU General Public License for more details.
                     13: 
                     14:     You should have received a copy of the GNU General Public License
                     15:     along with this program; if not, write to the Free Software
                     16:     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
                     17: */
                     18: 
                     19: #include "config.h"
                     20: 
                     21: #include <errno.h>
                     22: #include <stdio.h>
                     23: #include <stdlib.h>
                     24: #include <string.h>
                     25: #include <unistd.h>
                     26: 
                     27: #ifdef HAVE_LIBCAP
                     28: #include <sys/capability.h>
                     29: #endif
                     30: 
                     31: #include "wait.h"
                     32: 
                     33: /*  Drop SUID privileges.  To be used after accquiring raw sockets.  */
                     34: static
                     35: int drop_elevated_permissions(
                     36:     void)
                     37: {
                     38: #ifdef HAVE_LIBCAP
                     39:     cap_t cap;
                     40: #endif
                     41: 
                     42:     /*  Drop any suid permissions granted  */
                     43:     if (setgid(getgid()) || setuid(getuid())) {
                     44:         return -1;
                     45:     }
                     46: 
                     47:     if (geteuid() != getuid() || getegid() != getgid()) {
                     48:         return -1;
                     49:     }
                     50: 
                     51:     /*
                     52:        Drop all process capabilities.
                     53:        This will revoke anything granted by a commandline 'setcap'
                     54:      */
                     55: #ifdef HAVE_LIBCAP
                     56:     cap = cap_get_proc();
                     57:     if (cap == NULL) {
                     58:         return -1;
                     59:     }
                     60:     if (cap_clear(cap)) {
                     61:         return -1;
                     62:     }
                     63:     if (cap_set_proc(cap)) {
                     64:         return -1;
                     65:     }
                     66: #endif
                     67: 
                     68:     return 0;
                     69: }
                     70: 
                     71: int main(
                     72:     int argc,
                     73:     char **argv)
                     74: {
                     75:     bool command_pipe_open;
                     76:     struct command_buffer_t command_buffer;
                     77:     struct net_state_t net_state;
                     78: 
                     79:     /*
                     80:        To minimize security risk, the only thing done prior to 
                     81:        dropping SUID should be opening the network state for
                     82:        raw sockets.
                     83:      */
                     84:     init_net_state_privileged(&net_state);
                     85:     if (drop_elevated_permissions()) {
                     86:         perror("Unable to drop elevated permissions");
                     87:         exit(EXIT_FAILURE);
                     88:     }
                     89:     init_net_state(&net_state);
                     90: 
                     91:     init_command_buffer(&command_buffer, fileno(stdin));
                     92: 
                     93:     command_pipe_open = true;
                     94: 
                     95:     /*
                     96:        Dispatch commands and respond to probe replies until the
                     97:        command stream is closed.
                     98:      */
                     99:     while (true) {
                    100:         /*  Ensure any responses are written before waiting  */
                    101:         fflush(stdout);
                    102:         wait_for_activity(&command_buffer, &net_state);
                    103: 
                    104:         /*
                    105:            Receive replies first so that the timestamps are as
                    106:            close to the response arrival time as possible.
                    107:          */
                    108:         receive_replies(&net_state);
                    109: 
                    110:         if (command_pipe_open) {
                    111:             if (read_commands(&command_buffer)) {
                    112:                 if (errno == EPIPE) {
                    113:                     command_pipe_open = false;
                    114:                 }
                    115:             }
                    116:         }
                    117: 
                    118:         check_probe_timeouts(&net_state);
                    119: 
                    120:         /*
                    121:            Dispatch commands late so that the window between probe
                    122:            departure and arriving replies is as small as possible.
                    123:          */
                    124:         dispatch_buffer_commands(&command_buffer, &net_state);
                    125: 
                    126:         /*
                    127:            If the command pipe has been closed, exit after all
                    128:            in-flight probes have reported their status.
                    129:          */
                    130:         if (!command_pipe_open) {
                    131:             if (net_state.outstanding_probe_count == 0) {
                    132:                 break;
                    133:             }
                    134:         }
                    135:     }
                    136: 
                    137:     return 0;
                    138: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>