[network-manager-vpnc/NM_0_8] core/ui: add support for Hybrid authentication (lp:300628) (rh #677419) (bgo #495893) (debian #52961



commit 127f35b54334ea25017fa29d0e936097465ee673
Author: Mathieu Trudel-Lapierre <mathieu tl gmail com>
Date:   Fri Jul 15 16:28:55 2011 -0500

    core/ui: add support for Hybrid authentication (lp:300628) (rh #677419) (bgo #495893) (debian #529618)
    
    Here's a patch that implements hybrid authentication in the
    NetworkManager VPNC plugin. Many thanks to Steffan Roecker who did the
    original work.
    
    Essentially, this just passes over a certificate to be verified
    against in addition to the user/group names and passwords; and
    includes a bit of UI changes, since it's all starting to include quite
    a bit of stuff.
    
    (dcbw: rearranged the GtkBuilder layout a bit; made sure the
    advanced dialog got destroyed, was parented, and was modal, and
    made sure the certificate path gets verified in the daemon)

 properties/nm-vpnc-dialog.ui |  720 +++++++++++++++++++++++++++---------------
 properties/nm-vpnc.c         |  176 ++++++++++-
 src/nm-vpnc-service.c        |  168 ++++++----
 src/nm-vpnc-service.h        |    2 +
 4 files changed, 744 insertions(+), 322 deletions(-)
---
diff --git a/properties/nm-vpnc-dialog.ui b/properties/nm-vpnc-dialog.ui
index e26952d..4e1d359 100644
--- a/properties/nm-vpnc-dialog.ui
+++ b/properties/nm-vpnc-dialog.ui
@@ -1,10 +1,14 @@
-<?xml version="1.0"?>
-<!--*- mode: xml -*-->
+<?xml version="1.0" encoding="UTF-8"?>
 <interface>
-  <!-- interface-requires gtk+ 2.6 -->
-  <!-- interface-naming-policy toplevel-contextual -->
+  <requires lib="gtk+" version="2.24"/>
+  <object class="GtkImage" id="image1">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="stock">gtk-preferences</property>
+  </object>
   <object class="GtkListStore" id="model1">
     <columns>
+      <!-- column-name gchararray -->
       <column type="gchararray"/>
     </columns>
     <data>
@@ -15,6 +19,7 @@
   </object>
   <object class="GtkListStore" id="model2">
     <columns>
+      <!-- column-name gchararray -->
       <column type="gchararray"/>
     </columns>
     <data>
@@ -25,6 +30,7 @@
   </object>
   <object class="GtkListStore" id="model3">
     <columns>
+      <!-- column-name gchararray -->
       <column type="gchararray"/>
     </columns>
     <data>
@@ -35,6 +41,7 @@
   </object>
   <object class="GtkListStore" id="model4">
     <columns>
+      <!-- column-name gchararray -->
       <column type="gchararray"/>
     </columns>
     <data>
@@ -45,6 +52,7 @@
   </object>
   <object class="GtkListStore" id="model5">
     <columns>
+      <!-- column-name gchararray -->
       <column type="gchararray"/>
     </columns>
     <data>
@@ -53,254 +61,161 @@
       </row>
     </data>
   </object>
-      <object class="GtkVBox" id="vpnc-vbox">
+  <object class="GtkDialog" id="vpnc-advanced-dialog">
+    <property name="can_focus">False</property>
+    <property name="border_width">5</property>
+    <property name="title" translatable="yes">Advanced Options</property>
+    <property name="modal">True</property>
+    <property name="window_position">center</property>
+    <property name="destroy_with_parent">True</property>
+    <property name="icon_name">stock-preferences</property>
+    <property name="type_hint">dialog</property>
+    <property name="skip_taskbar_hint">True</property>
+    <child internal-child="vbox">
+      <object class="GtkBox" id="dialog-vbox1">
         <property name="visible">True</property>
-        <property name="border_width">12</property>
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
         <property name="spacing">16</property>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox" id="dialog-action_area1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="apply_button">
+                <property name="label">gtk-apply</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_action_appearance">False</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
         <child>
-          <object class="GtkVBox" id="vbox8">
+          <object class="GtkVBox" id="vbox2">
             <property name="visible">True</property>
+            <property name="can_focus">False</property>
             <property name="spacing">6</property>
             <child>
-              <object class="GtkLabel" id="label22">
+              <object class="GtkLabel" id="label1">
                 <property name="visible">True</property>
+                <property name="can_focus">False</property>
                 <property name="xalign">0</property>
-                <property name="label" translatable="yes">&lt;b&gt;General&lt;/b&gt;</property>
-                <property name="use_markup">True</property>
+                <property name="label" translatable="yes">Identification</property>
+                <attributes>
+                  <attribute name="weight" value="bold"/>
+                </attributes>
               </object>
               <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
               </packing>
             </child>
             <child>
-              <object class="GtkAlignment" id="alignment8">
+              <object class="GtkAlignment" id="alignment11">
                 <property name="visible">True</property>
+                <property name="can_focus">False</property>
                 <property name="left_padding">12</property>
                 <child>
-                  <object class="GtkTable" id="table2">
+                  <object class="GtkTable" id="table1">
                     <property name="visible">True</property>
-                    <property name="n_rows">5</property>
-                    <property name="n_columns">3</property>
+                    <property name="can_focus">False</property>
+                    <property name="n_columns">2</property>
                     <property name="column_spacing">6</property>
                     <property name="row_spacing">6</property>
                     <child>
-                      <placeholder/>
-                    </child>
-                    <child>
-                      <placeholder/>
-                    </child>
-                    <child>
-                      <placeholder/>
-                    </child>
-                    <child>
-                      <placeholder/>
-                    </child>
-                    <child>
-                      <object class="GtkComboBox" id="group_pass_type_combo">
-                        <property name="visible">True</property>
-                        <property name="model">model1</property>
-                        <child>
-                          <object class="GtkCellRendererText" id="renderer1"/>
-                          <attributes>
-                            <attribute name="text">0</attribute>
-                          </attributes>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="left_attach">2</property>
-                        <property name="right_attach">3</property>
-                        <property name="top_attach">3</property>
-                        <property name="bottom_attach">4</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkComboBox" id="user_pass_type_combo">
-                        <property name="visible">True</property>
-                        <property name="model">model2</property>
-                        <child>
-                          <object class="GtkCellRendererText" id="renderer2"/>
-                          <attributes>
-                            <attribute name="text">0</attribute>
-                          </attributes>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="left_attach">2</property>
-                        <property name="right_attach">3</property>
-                        <property name="top_attach">2</property>
-                        <property name="bottom_attach">3</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkCheckButton" id="show_passwords_checkbutton">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="label" translatable="yes">Show passwords</property>
-                        <property name="draw_indicator">True</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">4</property>
-                        <property name="bottom_attach">5</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkEntry" id="group_password_entry">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="visibility">False</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">3</property>
-                        <property name="bottom_attach">4</property>
-                        <property name="y_options"/>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label4">
-                        <property name="visible">True</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">Gro_up password:</property>
-                        <property name="use_underline">True</property>
-                        <property name="mnemonic_widget">group_entry</property>
-                      </object>
-                      <packing>
-                        <property name="top_attach">3</property>
-                        <property name="bottom_attach">4</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options"/>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label23">
-                        <property name="visible">True</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">_Gateway:</property>
-                        <property name="use_underline">True</property>
-                        <property name="mnemonic_widget">gateway_entry</property>
-                      </object>
-                      <packing>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options"/>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label24">
-                        <property name="visible">True</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">G_roup name:</property>
-                        <property name="use_underline">True</property>
-                        <property name="mnemonic_widget">group_entry</property>
-                      </object>
-                      <packing>
-                        <property name="top_attach">1</property>
-                        <property name="bottom_attach">2</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options"/>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkEntry" id="gateway_entry">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="y_options"/>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkEntry" id="group_entry">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">1</property>
-                        <property name="bottom_attach">2</property>
-                        <property name="y_options"/>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label3">
+                      <object class="GtkLabel" id="label27">
                         <property name="visible">True</property>
+                        <property name="can_focus">False</property>
                         <property name="xalign">0</property>
-                        <property name="label" translatable="yes">_User password:</property>
-                        <property name="use_underline">True</property>
-                        <property name="mnemonic_widget">group_entry</property>
+                        <property name="label" translatable="yes">Domain:</property>
                       </object>
                       <packing>
-                        <property name="top_attach">2</property>
-                        <property name="bottom_attach">3</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options"/>
+                        <property name="y_options"></property>
                       </packing>
                     </child>
                     <child>
-                      <object class="GtkEntry" id="user_password_entry">
+                      <object class="GtkEntry" id="domain_entry">
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
-                        <property name="visibility">False</property>
+                        <property name="invisible_char">â</property>
+                        <property name="invisible_char_set">True</property>
                       </object>
                       <packing>
                         <property name="left_attach">1</property>
                         <property name="right_attach">2</property>
-                        <property name="top_attach">2</property>
-                        <property name="bottom_attach">3</property>
-                        <property name="y_options"/>
+                        <property name="y_options"></property>
                       </packing>
                     </child>
                   </object>
                 </child>
               </object>
               <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
                 <property name="position">1</property>
               </packing>
             </child>
           </object>
           <packing>
-            <property name="expand">False</property>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
           </packing>
         </child>
         <child>
-          <object class="GtkVBox" id="vbox11">
+          <object class="GtkVBox" id="vbox3">
             <property name="visible">True</property>
+            <property name="can_focus">False</property>
             <property name="spacing">6</property>
             <child>
-              <object class="GtkLabel" id="label25">
+              <object class="GtkLabel" id="label2">
                 <property name="visible">True</property>
+                <property name="can_focus">False</property>
                 <property name="xalign">0</property>
-                <property name="label" translatable="yes">&lt;b&gt;Optional&lt;/b&gt;</property>
-                <property name="use_markup">True</property>
+                <property name="label" translatable="yes">Transport and Security</property>
+                <attributes>
+                  <attribute name="weight" value="bold"/>
+                </attributes>
               </object>
               <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
               </packing>
             </child>
             <child>
-              <object class="GtkAlignment" id="alignment9">
+              <object class="GtkAlignment" id="alignment2">
                 <property name="visible">True</property>
+                <property name="can_focus">False</property>
                 <property name="left_padding">12</property>
                 <child>
                   <object class="GtkTable" id="table3">
                     <property name="visible">True</property>
-                    <property name="n_rows">5</property>
+                    <property name="can_focus">False</property>
+                    <property name="n_rows">4</property>
                     <property name="n_columns">2</property>
                     <property name="column_spacing">6</property>
                     <property name="row_spacing">6</property>
                     <child>
-                      <placeholder/>
-                    </child>
-                    <child>
                       <object class="GtkComboBox" id="encryption_combo">
                         <property name="visible">True</property>
+                        <property name="can_focus">False</property>
                         <property name="model">model3</property>
                         <child>
                           <object class="GtkCellRendererText" id="renderer3"/>
@@ -312,83 +227,32 @@
                       <packing>
                         <property name="left_attach">1</property>
                         <property name="right_attach">2</property>
-                        <property name="top_attach">2</property>
-                        <property name="bottom_attach">3</property>
                       </packing>
                     </child>
                     <child>
-                      <object class="GtkLabel" id="label1">
+                      <object class="GtkLabel" id="label31">
                         <property name="visible">True</property>
+                        <property name="can_focus">False</property>
                         <property name="xalign">0</property>
                         <property name="label" translatable="yes">Encryption method:</property>
                       </object>
-                      <packing>
-                        <property name="top_attach">2</property>
-                        <property name="bottom_attach">3</property>
-                      </packing>
                     </child>
                     <child>
-                      <object class="GtkLabel" id="label26">
+                      <object class="GtkLabel" id="label41">
                         <property name="visible">True</property>
+                        <property name="can_focus">False</property>
                         <property name="xalign">0</property>
-                        <property name="label" translatable="yes">User name:</property>
-                      </object>
-                      <packing>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options"/>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkEntry" id="user_entry">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="y_options"/>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label27">
-                        <property name="visible">True</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">Domain:</property>
-                      </object>
-                      <packing>
-                        <property name="top_attach">1</property>
-                        <property name="bottom_attach">2</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options"/>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkEntry" id="domain_entry">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
+                        <property name="label" translatable="yes">NAT traversal:</property>
                       </object>
                       <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
                         <property name="top_attach">1</property>
                         <property name="bottom_attach">2</property>
-                        <property name="y_options"/>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label2">
-                        <property name="visible">True</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">NAT traversal:</property>
-                      </object>
-                      <packing>
-                        <property name="top_attach">3</property>
-                        <property name="bottom_attach">4</property>
                       </packing>
                     </child>
                     <child>
                       <object class="GtkComboBox" id="natt_combo">
                         <property name="visible">True</property>
+                        <property name="can_focus">False</property>
                         <property name="model">model4</property>
                         <child>
                           <object class="GtkCellRendererText" id="renderer4"/>
@@ -400,24 +264,26 @@
                       <packing>
                         <property name="left_attach">1</property>
                         <property name="right_attach">2</property>
-                        <property name="top_attach">3</property>
-                        <property name="bottom_attach">4</property>
+                        <property name="top_attach">1</property>
+                        <property name="bottom_attach">2</property>
                       </packing>
                     </child>
                     <child>
                       <object class="GtkLabel" id="label5">
                         <property name="visible">True</property>
+                        <property name="can_focus">False</property>
                         <property name="xalign">0</property>
                         <property name="label" translatable="yes">IKE DH Group:</property>
                       </object>
                       <packing>
-                        <property name="top_attach">4</property>
-                        <property name="bottom_attach">5</property>
+                        <property name="top_attach">2</property>
+                        <property name="bottom_attach">3</property>
                       </packing>
                     </child>
                     <child>
                       <object class="GtkComboBox" id="dhgroup_combo">
                         <property name="visible">True</property>
+                        <property name="can_focus">False</property>
                         <property name="model">model5</property>
                         <child>
                           <object class="GtkCellRendererText" id="renderer5"/>
@@ -429,37 +295,391 @@
                       <packing>
                         <property name="left_attach">1</property>
                         <property name="right_attach">2</property>
-                        <property name="top_attach">4</property>
-                        <property name="bottom_attach">5</property>
+                        <property name="top_attach">2</property>
+                        <property name="bottom_attach">3</property>
                       </packing>
                     </child>
                     <child>
                       <object class="GtkCheckButton" id="disable_dpd_checkbutton">
+                        <property name="label" translatable="yes">Disable Dead Peer Detection</property>
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
-                        <property name="label" translatable="yes">Disable Dead Peer Detection</property>
+                        <property name="receives_default">False</property>
+                        <property name="use_action_appearance">False</property>
                         <property name="draw_indicator">True</property>
                       </object>
                       <packing>
                         <property name="left_attach">1</property>
                         <property name="right_attach">2</property>
-                        <property name="top_attach">5</property>
-                        <property name="bottom_attach">6</property>
+                        <property name="top_attach">3</property>
+                        <property name="bottom_attach">4</property>
                       </packing>
                     </child>
+                    <child>
+                      <placeholder/>
+                    </child>
                   </object>
                 </child>
               </object>
               <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
                 <property name="position">1</property>
               </packing>
             </child>
           </object>
           <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="0">apply_button</action-widget>
+    </action-widgets>
+  </object>
+  <object class="GtkVBox" id="vpnc-vbox">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="border_width">12</property>
+    <property name="spacing">16</property>
+    <child>
+      <object class="GtkVBox" id="vbox8">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="spacing">6</property>
+        <child>
+          <object class="GtkLabel" id="label22">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">0</property>
+            <property name="label" translatable="yes">&lt;b&gt;General&lt;/b&gt;</property>
+            <property name="use_markup">True</property>
+          </object>
+          <packing>
             <property name="expand">False</property>
             <property name="fill">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkAlignment" id="alignment8">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="left_padding">12</property>
+            <child>
+              <object class="GtkTable" id="table2">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="n_rows">8</property>
+                <property name="n_columns">3</property>
+                <property name="column_spacing">6</property>
+                <property name="row_spacing">6</property>
+                <child>
+                  <object class="GtkComboBox" id="group_pass_type_combo">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="model">model1</property>
+                    <child>
+                      <object class="GtkCellRendererText" id="renderer1"/>
+                      <attributes>
+                        <attribute name="text">0</attribute>
+                      </attributes>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="left_attach">2</property>
+                    <property name="right_attach">3</property>
+                    <property name="top_attach">4</property>
+                    <property name="bottom_attach">5</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkComboBox" id="user_pass_type_combo">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="model">model2</property>
+                    <child>
+                      <object class="GtkCellRendererText" id="renderer2"/>
+                      <attributes>
+                        <attribute name="text">0</attribute>
+                      </attributes>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="left_attach">2</property>
+                    <property name="right_attach">3</property>
+                    <property name="top_attach">2</property>
+                    <property name="bottom_attach">3</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkCheckButton" id="show_passwords_checkbutton">
+                    <property name="label" translatable="yes">Show passwords</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">False</property>
+                    <property name="use_action_appearance">False</property>
+                    <property name="xalign">0</property>
+                    <property name="draw_indicator">True</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="right_attach">2</property>
+                    <property name="top_attach">5</property>
+                    <property name="bottom_attach">6</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkEntry" id="group_password_entry">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="visibility">False</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="right_attach">2</property>
+                    <property name="top_attach">4</property>
+                    <property name="bottom_attach">5</property>
+                    <property name="y_options"></property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label4">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="xalign">0</property>
+                    <property name="label" translatable="yes">Gro_up password:</property>
+                    <property name="use_underline">True</property>
+                    <property name="mnemonic_widget">group_entry</property>
+                  </object>
+                  <packing>
+                    <property name="top_attach">4</property>
+                    <property name="bottom_attach">5</property>
+                    <property name="x_options">GTK_FILL</property>
+                    <property name="y_options"></property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label23">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="xalign">0</property>
+                    <property name="label" translatable="yes">_Gateway:</property>
+                    <property name="use_underline">True</property>
+                    <property name="mnemonic_widget">gateway_entry</property>
+                  </object>
+                  <packing>
+                    <property name="x_options">GTK_FILL</property>
+                    <property name="y_options"></property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label24">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="xalign">0</property>
+                    <property name="label" translatable="yes">G_roup name:</property>
+                    <property name="use_underline">True</property>
+                    <property name="mnemonic_widget">group_entry</property>
+                  </object>
+                  <packing>
+                    <property name="top_attach">3</property>
+                    <property name="bottom_attach">4</property>
+                    <property name="x_options">GTK_FILL</property>
+                    <property name="y_options"></property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkEntry" id="gateway_entry">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="right_attach">2</property>
+                    <property name="y_options"></property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkEntry" id="group_entry">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="right_attach">2</property>
+                    <property name="top_attach">3</property>
+                    <property name="bottom_attach">4</property>
+                    <property name="y_options"></property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label3">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="xalign">0</property>
+                    <property name="label" translatable="yes">_User password:</property>
+                    <property name="use_underline">True</property>
+                    <property name="mnemonic_widget">group_entry</property>
+                  </object>
+                  <packing>
+                    <property name="top_attach">2</property>
+                    <property name="bottom_attach">3</property>
+                    <property name="x_options">GTK_FILL</property>
+                    <property name="y_options"></property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkEntry" id="user_password_entry">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="visibility">False</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="right_attach">2</property>
+                    <property name="top_attach">2</property>
+                    <property name="bottom_attach">3</property>
+                    <property name="y_options"></property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkEntry" id="user_entry">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="invisible_char">â</property>
+                    <property name="invisible_char_set">True</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="right_attach">2</property>
+                    <property name="top_attach">1</property>
+                    <property name="bottom_attach">2</property>
+                    <property name="y_options"></property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label26">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="xalign">0</property>
+                    <property name="label" translatable="yes">User name:</property>
+                  </object>
+                  <packing>
+                    <property name="top_attach">1</property>
+                    <property name="bottom_attach">2</property>
+                    <property name="x_options">GTK_FILL</property>
+                    <property name="y_options"></property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkCheckButton" id="hybrid_checkbutton">
+                    <property name="label" translatable="yes">Use hybrid authenticaton</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">False</property>
+                    <property name="use_action_appearance">False</property>
+                    <property name="xalign">0</property>
+                    <property name="draw_indicator">True</property>
+                  </object>
+                  <packing>
+                    <property name="right_attach">3</property>
+                    <property name="top_attach">6</property>
+                    <property name="bottom_attach">7</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkAlignment" id="alignment4">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <object class="GtkLabel" id="cafile_label">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="xalign">0</property>
+                        <property name="xpad">24</property>
+                        <property name="label" translatable="yes">CA File:</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="top_attach">7</property>
+                    <property name="bottom_attach">8</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkFileChooserButton" id="ca_file_chooser">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="right_attach">2</property>
+                    <property name="top_attach">7</property>
+                    <property name="bottom_attach">8</property>
+                  </packing>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
             <property name="position">1</property>
           </packing>
         </child>
       </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">True</property>
+        <property name="position">0</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkAlignment" id="alignment1">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="xalign">1</property>
+        <property name="xscale">0</property>
+        <child>
+          <object class="GtkButton" id="advanced_button">
+            <property name="label">Advanced...</property>
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="receives_default">True</property>
+            <property name="use_action_appearance">False</property>
+            <property name="image">image1</property>
+            <property name="image_position">right</property>
+          </object>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">False</property>
+        <property name="pack_type">end</property>
+        <property name="position">1</property>
+      </packing>
+    </child>
+  </object>
 </interface>
diff --git a/properties/nm-vpnc.c b/properties/nm-vpnc.c
index 9130bd9..32f1e60 100644
--- a/properties/nm-vpnc.c
+++ b/properties/nm-vpnc.c
@@ -32,8 +32,11 @@
 #include <arpa/inet.h>
 #include <errno.h>
 #include <stdlib.h>
-#include <glib/gi18n-lib.h>
 #include <string.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <glib/gi18n-lib.h>
 #include <gtk/gtk.h>
 #include <gnome-keyring.h>
 #include <gnome-keyring-memory.h>
@@ -87,6 +90,7 @@ typedef struct {
 	GtkWidget *widget;
 	GtkSizeGroup *group;
 	gint orig_dpd_timeout;
+	GtkWidget *advanced_dialog;
 } VpncPluginUiWidgetPrivate;
 
 
@@ -165,6 +169,26 @@ stuff_changed_cb (GtkWidget *widget, gpointer user_data)
 	g_signal_emit_by_name (VPNC_PLUGIN_UI_WIDGET (user_data), "changed");
 }
 
+static void
+hybrid_toggled_cb (GtkWidget *widget, gpointer user_data)
+{
+	VpncPluginUiWidgetPrivate *priv = VPNC_PLUGIN_UI_WIDGET_GET_PRIVATE (user_data);
+	gboolean enabled = FALSE;
+	GtkWidget *cafile_label, *ca_file_chooser;
+
+	cafile_label = GTK_WIDGET (gtk_builder_get_object (priv->builder, "cafile_label"));
+	g_return_if_fail (cafile_label);
+	ca_file_chooser = GTK_WIDGET (gtk_builder_get_object (priv->builder, "ca_file_chooser"));
+	g_return_if_fail (ca_file_chooser);
+
+	enabled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+
+	gtk_widget_set_sensitive (cafile_label, enabled);
+	gtk_widget_set_sensitive (ca_file_chooser, enabled);
+
+	stuff_changed_cb (widget, user_data);
+}
+
 static gboolean
 fill_vpn_passwords (VpncPluginUiWidget *self, NMConnection *connection)
 {
@@ -368,6 +392,87 @@ init_one_pw_combo (VpncPluginUiWidget *self,
 	g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (pw_type_combo_changed_cb), self);
 }
 
+static void
+toggle_advanced_dialog_cb (GtkWidget *button, gpointer user_data)
+{
+	VpncPluginUiWidgetPrivate *priv = VPNC_PLUGIN_UI_WIDGET_GET_PRIVATE (user_data);
+	GtkWidget *toplevel;
+
+	if (gtk_widget_get_visible (priv->advanced_dialog))
+		gtk_widget_hide (priv->advanced_dialog);
+	else {
+		toplevel = gtk_widget_get_toplevel (priv->widget);
+		if (gtk_widget_is_toplevel (toplevel))
+			gtk_window_set_transient_for (GTK_WINDOW (priv->advanced_dialog), GTK_WINDOW (toplevel));
+		gtk_widget_show_all (priv->advanced_dialog);
+	}
+}
+
+static const char *
+find_tag (const char *tag, const char *buf, gsize len)
+{
+	gsize i, taglen;
+
+	taglen = strlen (tag);
+	if (len < taglen)
+		return NULL;
+
+	for (i = 0; i < len - taglen + 1; i++) {
+		if (memcmp (buf + i, tag, taglen) == 0)
+			return buf + i;
+	}
+	return NULL;
+}
+
+static const char *pem_cert_begin = "-----BEGIN CERTIFICATE-----";
+
+static gboolean
+cert_filter (const GtkFileFilterInfo *filter_info, gpointer data)
+{
+	char *contents = NULL, *p, *ext;
+	gsize bytes_read = 0;
+	gboolean show = FALSE;
+	struct stat statbuf;
+
+	if (!filter_info->filename)
+		return FALSE;
+
+	p = strrchr (filter_info->filename, '.');
+	if (!p)
+		return FALSE;
+
+	ext = g_ascii_strdown (p, -1);
+	if (!ext)
+		return FALSE;
+
+	if (strcmp (ext, ".pem") && strcmp (ext, ".crt") && strcmp (ext, ".cer")) {
+		g_free (ext);
+		return FALSE;
+	}
+	g_free (ext);
+
+	/* Ignore files that are really large */
+	if (!stat (filter_info->filename, &statbuf)) {
+		if (statbuf.st_size > 500000)
+			return FALSE;
+	}
+
+	if (!g_file_get_contents (filter_info->filename, &contents, &bytes_read, NULL))
+		return FALSE;
+
+	if (bytes_read < 400)  /* needs to be lower? */
+		goto out;
+
+	if (find_tag (pem_cert_begin, (const char *) contents, bytes_read)) {
+		show = TRUE;
+		goto out;
+	}
+
+out:
+	g_free (contents);
+	return show;
+}
+
 static gboolean
 init_plugin_ui (VpncPluginUiWidget *self, NMConnection *connection, GError **error)
 {
@@ -380,6 +485,8 @@ init_plugin_ui (VpncPluginUiWidget *self, NMConnection *connection, GError **err
 	int active = -1;
 	const char *natt_mode = NULL;
 	const char *ike_dh_group = NULL;
+	gboolean enabled = FALSE;
+	GtkFileFilter *filter;
 
 	s_vpn = (NMSettingVPN *) nm_connection_get_setting (connection, NM_TYPE_SETTING_VPN);
 
@@ -565,6 +672,60 @@ init_plugin_ui (VpncPluginUiWidget *self, NMConnection *connection, GError **err
 	                  (GCallback) show_toggled_cb,
 	                  self);
 
+	/* hybrid auth */
+
+	enabled = FALSE;
+	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "hybrid_checkbutton"));
+	g_return_val_if_fail (widget != NULL, FALSE);
+	if (s_vpn) {
+		value = nm_setting_vpn_get_data_item (s_vpn, NM_VPNC_KEY_AUTHMODE);
+		if (value && !strcmp("hybrid", value)) {
+			gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
+			enabled = TRUE;
+		}
+	}
+	g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (hybrid_toggled_cb), self);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "ca_file_chooser"));
+	g_return_val_if_fail (widget != NULL, FALSE);
+	gtk_size_group_add_widget (priv->group, widget);
+	gtk_widget_set_sensitive (widget, enabled);
+	gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (widget), TRUE);
+	gtk_file_chooser_button_set_title (GTK_FILE_CHOOSER_BUTTON (widget),
+	                                   _("Choose a Certificate Authority (CA) certificate..."));
+
+	filter = gtk_file_filter_new ();
+	gtk_file_filter_add_custom (filter, GTK_FILE_FILTER_FILENAME, cert_filter, NULL, NULL);
+	gtk_file_filter_set_name (filter, _("PEM certificates (*.pem, *.crt, *.cer)"));
+	gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (widget), filter);
+
+	if (s_vpn) {
+		value = nm_setting_vpn_get_data_item (s_vpn, NM_VPNC_KEY_CA_FILE);
+		if (value && strlen (value))
+			gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget), value);
+	}
+	g_signal_connect (G_OBJECT (widget), "file-set", G_CALLBACK (stuff_changed_cb), self);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "cafile_label"));
+	g_return_val_if_fail (widget != NULL, FALSE);
+	gtk_widget_set_sensitive (widget, enabled);
+
+	/* advanced dialog */
+
+	priv->advanced_dialog = GTK_WIDGET (gtk_builder_get_object (priv->builder, "vpnc-advanced-dialog"));
+	g_return_val_if_fail (priv->advanced_dialog != NULL, FALSE);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "advanced_button"));
+	g_return_val_if_fail (widget != NULL, FALSE);
+	g_signal_connect (G_OBJECT (widget), "clicked",
+	                  (GCallback) toggle_advanced_dialog_cb,
+	                  self);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "apply_button"));
+	g_return_val_if_fail (widget != NULL, FALSE);
+	g_signal_connect (G_OBJECT (widget), "clicked",
+	                  (GCallback) toggle_advanced_dialog_cb,
+	                  self);
 	return TRUE;
 }
 
@@ -725,6 +886,16 @@ update_connection (NMVpnPluginUiWidgetInterface *iface,
 			nm_setting_vpn_add_data_item (s_vpn, NM_VPNC_KEY_LOCAL_PORT, local_port);
 	}
 
+	/* hybrid auth */
+	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "hybrid_checkbutton"));
+	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
+		nm_setting_vpn_add_data_item (s_vpn, NM_VPNC_KEY_AUTHMODE, "hybrid");
+
+	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "ca_file_chooser"));
+	str = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
+	if (str && strlen (str))
+		nm_setting_vpn_add_data_item (s_vpn, NM_VPNC_KEY_CA_FILE, str);
+
 	nm_connection_add_setting (connection, NM_SETTING (s_vpn));
 	return TRUE;
 }
@@ -857,6 +1028,9 @@ dispose (GObject *object)
 	if (priv->widget)
 		g_object_unref (priv->widget);
 
+	if (priv->advanced_dialog)
+		gtk_widget_destroy (priv->advanced_dialog);
+
 	if (priv->builder)
 		g_object_unref (priv->builder);
 
diff --git a/src/nm-vpnc-service.c b/src/nm-vpnc-service.c
index f933a66..96740c8 100644
--- a/src/nm-vpnc-service.c
+++ b/src/nm-vpnc-service.c
@@ -62,9 +62,18 @@ static const char *vpnc_binary_paths[] =
 #define NM_VPNC_UDP_ENCAPSULATION_PORT	0 /* random port */
 #define NM_VPNC_LOCAL_PORT_ISAKMP	0 /* random port */
 
+typedef enum {
+	ITEM_TYPE_UNKNOWN = 0,
+	ITEM_TYPE_IGNORED,
+	ITEM_TYPE_STRING,
+	ITEM_TYPE_BOOLEAN,
+	ITEM_TYPE_INT,
+	ITEM_TYPE_PATH
+} ItemType;
+
 typedef struct {
 	const char *name;
-	GType type;
+	guint32 type;
 	gint int_min;
 	gint int_max;
 } ValidProperty;
@@ -72,32 +81,35 @@ typedef struct {
 #define LEGACY_NAT_KEEPALIVE "NAT-Keepalive packet interval"
 
 static ValidProperty valid_properties[] = {
-	{ NM_VPNC_KEY_GATEWAY,               G_TYPE_STRING, 0, 0 },
-	{ NM_VPNC_KEY_ID,                    G_TYPE_STRING, 0, 0 },
-	{ NM_VPNC_KEY_XAUTH_USER,            G_TYPE_STRING, 0, 0 },
-	{ NM_VPNC_KEY_DOMAIN,                G_TYPE_STRING, 0, 0 },
-	{ NM_VPNC_KEY_DHGROUP,               G_TYPE_STRING, 0, 0 },
-	{ NM_VPNC_KEY_PERFECT_FORWARD,       G_TYPE_STRING, 0, 0 },
-	{ NM_VPNC_KEY_VENDOR,                G_TYPE_STRING, 0, 0 },
-	{ NM_VPNC_KEY_APP_VERSION,           G_TYPE_STRING, 0, 0 },
-	{ NM_VPNC_KEY_SINGLE_DES,            G_TYPE_BOOLEAN, 0, 0 },
-	{ NM_VPNC_KEY_NO_ENCRYPTION,         G_TYPE_BOOLEAN, 0, 0 },
-	{ NM_VPNC_KEY_DPD_IDLE_TIMEOUT,      G_TYPE_INT, 0, 86400 },
-	{ NM_VPNC_KEY_NAT_TRAVERSAL_MODE,    G_TYPE_STRING, 0, 0 },
-	{ NM_VPNC_KEY_CISCO_UDP_ENCAPS_PORT, G_TYPE_INT, 0, 65535 },
-	{ NM_VPNC_KEY_LOCAL_PORT,            G_TYPE_INT, 0, 65535 },
+	{ NM_VPNC_KEY_GATEWAY,               ITEM_TYPE_STRING, 0, 0 },
+	{ NM_VPNC_KEY_ID,                    ITEM_TYPE_STRING, 0, 0 },
+	{ NM_VPNC_KEY_XAUTH_USER,            ITEM_TYPE_STRING, 0, 0 },
+	{ NM_VPNC_KEY_DOMAIN,                ITEM_TYPE_STRING, 0, 0 },
+	{ NM_VPNC_KEY_DHGROUP,               ITEM_TYPE_STRING, 0, 0 },
+	{ NM_VPNC_KEY_PERFECT_FORWARD,       ITEM_TYPE_STRING, 0, 0 },
+	{ NM_VPNC_KEY_VENDOR,                ITEM_TYPE_STRING, 0, 0 },
+	{ NM_VPNC_KEY_APP_VERSION,           ITEM_TYPE_STRING, 0, 0 },
+	{ NM_VPNC_KEY_SINGLE_DES,            ITEM_TYPE_BOOLEAN, 0, 0 },
+	{ NM_VPNC_KEY_NO_ENCRYPTION,         ITEM_TYPE_BOOLEAN, 0, 0 },
+	{ NM_VPNC_KEY_DPD_IDLE_TIMEOUT,      ITEM_TYPE_INT, 0, 86400 },
+	{ NM_VPNC_KEY_NAT_TRAVERSAL_MODE,    ITEM_TYPE_STRING, 0, 0 },
+	{ NM_VPNC_KEY_CISCO_UDP_ENCAPS_PORT, ITEM_TYPE_INT, 0, 65535 },
+	{ NM_VPNC_KEY_LOCAL_PORT,            ITEM_TYPE_INT, 0, 65535 },
+	/* Hybrid Auth */
+	{ NM_VPNC_KEY_AUTHMODE,              ITEM_TYPE_STRING, 0, 0 },
+	{ NM_VPNC_KEY_CA_FILE,               ITEM_TYPE_PATH, 0, 0 },
 	/* Ignored option for internal use */
-	{ NM_VPNC_KEY_SECRET_TYPE,           G_TYPE_NONE, 0, 0 },
-	{ NM_VPNC_KEY_XAUTH_PASSWORD_TYPE,   G_TYPE_NONE, 0, 0 },
+	{ NM_VPNC_KEY_SECRET_TYPE,           ITEM_TYPE_IGNORED, 0, 0 },
+	{ NM_VPNC_KEY_XAUTH_PASSWORD_TYPE,   ITEM_TYPE_IGNORED, 0, 0 },
 	/* Legacy options that are ignored */
-	{ LEGACY_NAT_KEEPALIVE,              G_TYPE_STRING, 0, 0 },
-	{ NULL,                              G_TYPE_NONE, 0, 0 }
+	{ LEGACY_NAT_KEEPALIVE,              ITEM_TYPE_STRING, 0, 0 },
+	{ NULL,                              ITEM_TYPE_UNKNOWN, 0, 0 }
 };
 
 static ValidProperty valid_secrets[] = {
-	{ NM_VPNC_KEY_SECRET,                G_TYPE_STRING, 0, 0 },
-	{ NM_VPNC_KEY_XAUTH_PASSWORD,        G_TYPE_STRING, 0, 0 },
-	{ NULL,                              G_TYPE_NONE, 0, 0 }
+	{ NM_VPNC_KEY_SECRET,                ITEM_TYPE_STRING, 0, 0 },
+	{ NM_VPNC_KEY_XAUTH_PASSWORD,        ITEM_TYPE_STRING, 0, 0 },
+	{ NULL,                              ITEM_TYPE_UNKNOWN, 0, 0 }
 };
 
 typedef struct ValidateInfo {
@@ -110,6 +122,8 @@ static void
 validate_one_property (const char *key, const char *value, gpointer user_data)
 {
 	ValidateInfo *info = (ValidateInfo *) user_data;
+	ValidProperty *prop = NULL;
+	long int tmp;
 	int i;
 
 	if (*(info->error))
@@ -122,56 +136,68 @@ validate_one_property (const char *key, const char *value, gpointer user_data)
 		return;
 
 	for (i = 0; info->table[i].name; i++) {
-		ValidProperty prop = info->table[i];
-		long int tmp;
-
-		if (strcmp (prop.name, key))
-			continue;
-
-		switch (prop.type) {
-		case G_TYPE_NONE:
-			return; /* technically valid, but unused */
-		case G_TYPE_STRING:
-			return; /* valid */
-		case G_TYPE_INT:
-			errno = 0;
-			tmp = strtol (value, NULL, 10);
-			if (errno == 0 && tmp >= prop.int_min && tmp <= prop.int_max)
-				return; /* valid */
-
-			g_set_error (info->error,
-			             NM_VPN_PLUGIN_ERROR,
-			             NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
-			             "invalid integer property '%s' or out of range [%d -> %d]",
-			             key, prop.int_min, prop.int_max);
+		prop = &info->table[i];
+		if (g_strcmp0 (prop->name, key) == 0)
 			break;
-		case G_TYPE_BOOLEAN:
-			if (!strcmp (value, "yes") || !strcmp (value, "no"))
-				return; /* valid */
+	}
 
+	/* Did not find the property from valid_properties or the type did not match */
+	if (!prop || !prop->name) {
+		g_set_error (info->error,
+		             NM_VPN_PLUGIN_ERROR,
+		             NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
+		             "property '%s' invalid or not supported",
+		             key);
+		return;
+	}
+
+	/* Validate the property */
+	switch (prop->type) {
+	case ITEM_TYPE_IGNORED:
+		break; /* technically valid, but unused */
+	case ITEM_TYPE_STRING:
+		break; /* valid */
+	case ITEM_TYPE_PATH:
+		if (   !value
+		    || !strlen (value)
+		    || !g_path_is_absolute (value)
+		    || !g_file_test (value, G_FILE_TEST_EXISTS)) {
 			g_set_error (info->error,
 			             NM_VPN_PLUGIN_ERROR,
 			             NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
-			             "invalid boolean property '%s' (not yes or no)",
-			             key);
-			break;
-		default:
-			g_set_error (info->error,
-			             NM_VPN_PLUGIN_ERROR,
-			             NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
-			             "unhandled property '%s' type %s",
-			             key, g_type_name (prop.type));
-			break;
+			             "property '%s' file path '%s' is not absolute or does not exist",
+			             key, value);
 		}
-	}
+		break;
+	case ITEM_TYPE_INT:
+		errno = 0;
+		tmp = strtol (value, NULL, 10);
+		if (errno == 0 && tmp >= prop->int_min && tmp <= prop->int_max)
+			break; /* valid */
 
-	/* Did not find the property from valid_properties or the type did not match */
-	if (!info->table[i].name) {
 		g_set_error (info->error,
 		             NM_VPN_PLUGIN_ERROR,
 		             NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
-		             "property '%s' invalid or not supported",
+		             "invalid integer property '%s' or out of range [%d -> %d]",
+		             key, prop->int_min, prop->int_max);
+		break;
+	case ITEM_TYPE_BOOLEAN:
+		if (!strcmp (value, "yes") || !strcmp (value, "no"))
+			break; /* valid */
+
+		g_set_error (info->error,
+		             NM_VPN_PLUGIN_ERROR,
+		             NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
+		             "invalid boolean property '%s' (not yes or no)",
 		             key);
+		break;
+	default:
+		g_set_error (info->error,
+		             NM_VPN_PLUGIN_ERROR,
+		             NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
+		             "unhandled property '%s' type %d",
+		             key, prop->type);
+		break;
 	}
 }
 
@@ -333,7 +359,7 @@ static void
 write_one_property (const char *key, const char *value, gpointer user_data)
 {
 	WriteConfigInfo *info = (WriteConfigInfo *) user_data;
-	GType type = G_TYPE_INVALID;
+	guint32 type = ITEM_TYPE_UNKNOWN;
 	int i;
 
 	if (info->error)
@@ -351,7 +377,7 @@ write_one_property (const char *key, const char *value, gpointer user_data)
 	}
 
 	/* Try the valid secrets table */
-	for (i = 0; type == G_TYPE_INVALID && valid_secrets[i].name; i++) {
+	for (i = 0; type == ITEM_TYPE_UNKNOWN && valid_secrets[i].name; i++) {
 		ValidProperty prop = valid_secrets[i];
 
 		if (!strcmp (prop.name, (char *) key)) {
@@ -361,13 +387,14 @@ write_one_property (const char *key, const char *value, gpointer user_data)
 		}
 	}
 
-	if (type == G_TYPE_INVALID) {
+	if (type == ITEM_TYPE_UNKNOWN) {
 		g_set_error (&info->error,
 		             NM_VPN_PLUGIN_ERROR,
 		             NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
 		             "Config option '%s' invalid or unknown.",
 		             (const char *) key);
-	}	
+		return;
+	}
 
 	/* Don't write ignored secrets */
 	if (!strcmp (key, NM_VPNC_KEY_XAUTH_PASSWORD) && info->upw_ignored)
@@ -375,12 +402,12 @@ write_one_property (const char *key, const char *value, gpointer user_data)
 	if (!strcmp (key, NM_VPNC_KEY_SECRET) && info->gpw_ignored)
 		return;
 
-	if (type == G_TYPE_STRING)
+	if (type == ITEM_TYPE_STRING || type == ITEM_TYPE_PATH)
 		write_config_option (info->fd, "%s %s\n", (char *) key, (char *) value);
-	else if (type == G_TYPE_BOOLEAN) {
+	else if (type == ITEM_TYPE_BOOLEAN) {
 		if (!strcmp (value, "yes"))
 			write_config_option (info->fd, "%s\n", (char *) key);
-	} else if (type == G_TYPE_INT) {
+	} else if (type == ITEM_TYPE_INT) {
 		long int tmp_int;
 		char *tmp_str;
 
@@ -400,12 +427,11 @@ write_one_property (const char *key, const char *value, gpointer user_data)
 			             "Config option '%s' not an integer.",
 			             (const char *) key);
 		}
-	} else if (type == G_TYPE_NONE) {
+	} else if (type == ITEM_TYPE_IGNORED) {
 		/* ignored */
 	} else {
 		/* Just ignore unknown properties */
-		nm_warning ("Don't know how to write property '%s' with type %s",
-				  (char *) key, g_type_name (type));
+		g_warning ("Don't know how to write property '%s' with type %d", key, type);
 	}
 }
 
diff --git a/src/nm-vpnc-service.h b/src/nm-vpnc-service.h
index e3bcbf4..cf9b6ea 100644
--- a/src/nm-vpnc-service.h
+++ b/src/nm-vpnc-service.h
@@ -55,6 +55,8 @@
 #define NM_VPNC_KEY_DPD_IDLE_TIMEOUT "DPD idle timeout (our side)"
 #define NM_VPNC_KEY_CISCO_UDP_ENCAPS_PORT "Cisco UDP Encapsulation Port"
 #define NM_VPNC_KEY_LOCAL_PORT "Local Port"
+#define NM_VPNC_KEY_AUTHMODE "IKE Authmode"
+#define NM_VPNC_KEY_CA_FILE "CA-File"
 
 #define NM_VPNC_NATT_MODE_NATT        "natt"
 #define NM_VPNC_NATT_MODE_NONE        "none"



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]