Annotation of embedaddon/mtr/packet/packet.c, revision 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>