imv-scanner: Properly check snprintf() return value
[strongswan.git] / src / libimcv / plugins / imv_scanner / imv_scanner_agent.c
index 1757783..d1e0931 100644 (file)
@@ -255,20 +255,26 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
                return TNC_RESULT_SUCCESS;
        }
 
+       /* create an empty out message - we might need it */
+       out_msg = imv_msg_create(this->agent, state, id, imv_id, TNC_IMCID_ANY,
+                                                        msg_types[0]);
+
        if (!session)
        {
                DBG2(DBG_IMV, "no workitems available - no evaluation possible");
                state->set_recommendation(state,
                                                        TNC_IMV_ACTION_RECOMMENDATION_ALLOW,
                                                        TNC_IMV_EVALUATION_RESULT_DONT_KNOW);
-               scanner_state->set_handshake_state(scanner_state,
-                                                       IMV_SCANNER_STATE_END);
-               return TNC_RESULT_SUCCESS;
-       }
+               result = out_msg->send_assessment(out_msg);
+               out_msg->destroy(out_msg);
+               scanner_state->set_handshake_state(scanner_state, IMV_SCANNER_STATE_END);
 
-       /* create an empty out message - we might need it */
-       out_msg = imv_msg_create(this->agent, state, id, imv_id, TNC_IMCID_ANY,
-                                                        msg_types[0]);
+               if (result != TNC_RESULT_SUCCESS)
+               {
+                       return result;
+               }
+               return this->agent->provide_recommendation(this->agent, state);
+       }
 
        if (handshake_state == IMV_SCANNER_STATE_INIT)
        {
@@ -324,7 +330,10 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
                TNC_IMV_Action_Recommendation rec;
                u_int8_t protocol_family, protocol;
                u_int16_t port;
-               bool closed_port_policy, blocked;
+               bool closed_port_policy, blocked, first;
+               char result_str[BUF_LEN], *pos, *protocol_str;
+               size_t len;
+               int written;
                linked_list_t *port_list;
                enumerator_t *e1, *e2;
 
@@ -360,6 +369,11 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
                        }
                        port_list = get_port_list(protocol_family, closed_port_policy,
                                                                          workitem->get_arg_str(workitem));
+                       protocol_str = (protocol_family == IPPROTO_TCP) ? "tcp" : "udp";
+                       result_str[0] = '\0';
+                       pos = result_str;
+                       len = BUF_LEN;
+                       first = TRUE;
 
                        e1 = port_filter_attr->create_port_enumerator(port_filter_attr);
                        while (e1->enumerate(e1, &blocked, &protocol, &port))
@@ -386,42 +400,67 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
                                e2->destroy(e2);
 
                                passed = (closed_port_policy == found);
-                               DBG2(DBG_IMV, "%s port %5u open: %s",
-                                       (protocol == IPPROTO_TCP) ? "tcp" : "udp", port,
-                                        passed ? "ok" : "fatal");
+                               DBG2(DBG_IMV, "%s port %5u open: %s", protocol_str, port,
+                                                          passed ? "ok" : "fatal");
                                if (!passed)
                                {
                                        eval = TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR;
-                                       snprintf(buf, sizeof(buf), "%s/%u",
-                                                       (protocol == IPPROTO_TCP) ? "tcp" : "udp", port);
+                                       snprintf(buf, sizeof(buf), "%s/%u", protocol_str, port);
                                        scanner_state->add_violating_port(scanner_state, strdup(buf));
+                                       if (first)
+                                       {
+                                               written = snprintf(pos, len, "violating %s ports:",
+                                                                                                         protocol_str);
+                                               if (written > 0 && written < len)
+                                               {
+                                                       pos += written;
+                                                       len -= written;
+                                               }
+                                               first = FALSE;
+                                       }
+                                       written = snprintf(pos, len, " %u", port);
+                                       if (written < 0 || written >= len)
+                                       {
+                                               pos += len - 1;
+                                               *pos = '\0';
+                                       }
+                                       else
+                                       {
+                                               pos += written;
+                                               len -= written;
+                                       }
                                }
                        }
                        e1->destroy(e1);
 
+                       if (first)
+                       {
+                               snprintf(pos, len, "no violating %s ports", protocol_str);
+                       }
                        port_list->destroy(port_list);
 
                        session->remove_workitem(session, enumerator);
-                       rec = workitem->set_result(workitem, "", eval);
+                       rec = workitem->set_result(workitem, result_str, eval);
                        state->update_recommendation(state, rec, eval);
                        imcv_db->finalize_workitem(imcv_db, workitem);
                        workitem->destroy(workitem);
                }
                enumerator->destroy(enumerator);
+       }
 
-               /* finalized all workitems ? */
-               if (session->get_workitem_count(session, imv_id) == 0)
+       /* finalized all workitems ? */
+       if (handshake_state == IMV_SCANNER_STATE_WORKITEMS &&
+               session->get_workitem_count(session, imv_id) == 0)
+       {
+               result = out_msg->send_assessment(out_msg);
+               out_msg->destroy(out_msg);
+               scanner_state->set_handshake_state(scanner_state, IMV_SCANNER_STATE_END);
+
+               if (result != TNC_RESULT_SUCCESS)
                {
-                       scanner_state->set_handshake_state(scanner_state,
-                                                                                          IMV_SCANNER_STATE_END);
-                       result = out_msg->send_assessment(out_msg);
-                       out_msg->destroy(out_msg);
-                       if (result != TNC_RESULT_SUCCESS)
-                       {
-                               return result;
-                       }
-                       return this->agent->provide_recommendation(this->agent, state);
+                       return result;
                }
+               return this->agent->provide_recommendation(this->agent, state);
        }
 
        /* send non-empty PA-TNC message with excl flag not set */
@@ -468,7 +507,7 @@ imv_agent_if_t *imv_scanner_agent_create(const char *name, TNC_IMVID id,
        {
                return NULL;
        }
-       
+
        INIT(this,
                .public = {
                        .bind_functions = _bind_functions,