1 /*
2
3 Firewall Builder
4
5 Copyright (C) 2008 NetCitadel, LLC
6
7 Author: Vadim Kurland vadim@fwbuilder.org
8
9 $Id$
10
11 This program is free software which we release under the GNU General Public
12 License. You may redistribute and/or modify this program under the terms
13 of that license as published by the Free Software Foundation; either
14 version 2 of the License, or (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 To get a copy of the GNU General Public License, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23
24 */
25
26 #include "config.h"
27 #include "global.h"
28 #include "utils.h"
29 #include "utils_no_qt.h"
30
31 #include "FirewallInstallerCisco.h"
32 #include "instDialog.h"
33 #include "SSHPIX.h"
34 #include "SSHIOS.h"
35 #include "SSHNXOS.h"
36 #include "Configlet.h"
37
38 #include "fwbuilder/Resources.h"
39 #include "fwbuilder/FWObjectDatabase.h"
40 #include "fwbuilder/Firewall.h"
41 #include "fwbuilder/XMLTools.h"
42 #include "fwbuilder/Interface.h"
43 #include "fwbuilder/Management.h"
44 #include "fwbuilder/XMLTools.h"
45
46 #include <QFileInfo>
47 #include <QTextStream>
48 #include <QMessageBox>
49 #include <QtDebug>
50
51 using namespace std;
52 using namespace libfwbuilder;
53
54
FirewallInstallerCisco(instDialog * _dlg,instConf * _cnf,const QString & _p)55 FirewallInstallerCisco::FirewallInstallerCisco(instDialog *_dlg,
56 instConf *_cnf, const QString &_p):
57 FirewallInstaller(_dlg, _cnf, _p)
58 {
59 // string platform = cnf->fwobj->getStr("platform");
60 // if (cnf->fwdir.isEmpty())
61 // {
62 // if (platform=="nxosacl") cnf->fwdir = "volatile:";
63 // else cnf->fwdir = "flash:";
64 // }
65 }
66
packInstallJobsList(Firewall *)67 bool FirewallInstallerCisco::packInstallJobsList(Firewall*)
68 {
69 if (fwbdebug)
70 qDebug("FirewallInstallerCisco::packInstallJobList script=%s",
71 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
72 cnf->script.toAscii().constData());
73 #else
74 cnf->script.toLatin1().constData());
75 #endif
76 job_list.clear();
77
78 Management *mgmt = cnf->fwobj->getManagementObject();
79 assert(mgmt!=NULL);
80 PolicyInstallScript *pis = mgmt->getPolicyInstallScript();
81 if (pis->getCommand()!="")
82 {
83 QString cmd = pis->getCommand().c_str();
84 QString args = pis->getArguments().c_str();
85 job_list.push_back(
86 instJob(RUN_EXTERNAL_SCRIPT, cmd, args));
87 inst_dlg->addToLog(QString("Run script %1 %2\n").arg(cmd).arg(args));
88 return true;
89 }
90
91 // Load configuration file early so we can abort installation if
92 // it is not accessible
93
94 // Note about option "install only acl, icmp, telnet, ssh, nat,
95 // global and static" for PIX. This option used to read generated
96 // config but cuts off everything before the magic comment line
97 // "!################". This way, it only read object-group,
98 // access-list, access-group, nat, static and global commands. It
99 // skipped all interface configurations, timeouts and inspector
100 // commands. It is difficult to implement now that we (can) use
101 // scp to copy configuration to the firewall. We would have to
102 // create temporary file with modified configuration in order to
103 // do this. To avoid hassles with temporary files, we move the
104 // same function to the compiler. The checkbox moves to the
105 // "script" tab of the pix advanced settings dialog and when it is on,
106 // compiler generates the script with only acl, icmp, telnet, ssh
107 // nat,static and global commands
108 //
109 // This mode of installation is not supported on IOS at all.
110
111 QString ff;
112 QFileInfo script_info(cnf->script);
113 if (script_info.isAbsolute()) ff = cnf->script;
114 else ff = cnf->wdir + "/" + cnf->script;
115
116 QFile data(ff);
117 if (data.open(QFile::ReadOnly))
118 {
119 QTextStream strm(&data);
120 QString line;
121 do
122 {
123 line = strm.readLine();
124 config_lines.push_back(line.trimmed());
125 } while (!strm.atEnd());
126 } else
127 {
128 QMessageBox::critical(
129 inst_dlg, "Firewall Builder",
130 tr("Can not read generated script %1").arg(ff),
131 tr("&Continue"), QString::null,QString::null,
132 0, 1 );
133 return false;
134 }
135
136 string platform = cnf->fwobj->getStr("platform");
137
138 if (cnf->useSCPForRouter)
139 {
140 QMap<QString,QString> all_files;
141
142 // readManifest() modifies cnf (assigns cnf->remote_script) !
143 if (readManifest(cnf->script, &all_files))
144 {
145 QMap<QString, QString>::iterator it;
146 for (it=all_files.begin(); it!=all_files.end(); ++it)
147 {
148 QString local_name = it.key();
149 QString remote_name = it.value();
150 job_list.push_back(instJob(COPY_FILE, local_name, remote_name));
151 }
152 }
153
154 QString cmd = getActivationCmd();
155 job_list.push_back(instJob(ACTIVATE_POLICY, cmd, ""));
156 } else
157 {
158 job_list.push_back(instJob(ACTIVATE_POLICY, cnf->script, ""));
159 }
160
161 return true;
162 }
163
activatePolicy(const QString &,const QString &)164 void FirewallInstallerCisco::activatePolicy(const QString&, const QString&)
165 {
166 QStringList args;
167
168 packSSHArgs(args);
169 if (cnf->verbose) inst_dlg->displayCommand(args);
170
171 SSHCisco *ssh_object = NULL;
172 if (cnf->fwobj->getStr("platform")=="pix" ||
173 cnf->fwobj->getStr("platform")=="fwsm")
174 {
175 ssh_object = new SSHPIX(inst_dlg,
176 cnf->fwobj->getName().c_str(),
177 args,
178 cnf->pwd,
179 cnf->epwd,
180 list<string>());
181 } else if (cnf->fwobj->getStr("platform")=="nxosacl")
182 {
183 ssh_object = new SSHNXOS(inst_dlg,
184 cnf->fwobj->getName().c_str(),
185 args,
186 cnf->pwd,
187 cnf->epwd,
188 list<string>());
189 } else // ios
190 {
191 ssh_object = new SSHIOS(inst_dlg,
192 cnf->fwobj->getName().c_str(),
193 args,
194 cnf->pwd,
195 cnf->epwd,
196 list<string>());
197 }
198 /*
199 * TODO:
200 * the structure of scriptlets (command templates) for PIX and
201 * IOS is nice and generic, it uses generalized "pre_config"
202 * and "post_config" hooks in SSHPIX / SSHIOS classes. Need to
203 * do the same for Unix firewalls.
204 */
205
206 QString cmd = "";
207 QStringList pre_config_commands;
208 QStringList post_config_commands;
209
210 string version = cnf->fwobj->getStr("version");
211 bool version_lt_124 = XMLTools::version_compare(version, "12.4") < 0;
212 bool version_ge_124 = XMLTools::version_compare(version, "12.4") >= 0;
213
214 string host_os = cnf->fwobj->getStr("host_OS");
215 string os_family = Resources::os_res[host_os]->
216 getResourceStr("/FWBuilderResources/Target/family");
217
218 // installer configlets should be different for each OS, but if
219 // some OS can use the same script, it will be placed in the file
220 // under os_family name. For example:
221 // for PIX configlet is in src/res/configlets/pix_os
222 // but since fwsm and pix can use the same script and fwsm_os.xml
223 // declares family as "pix_os", it uses the same configlet.
224
225 Configlet pre_config(host_os, os_family, "installer_commands_pre_config");
226 pre_config.removeComments();
227
228 // test run and rollback were deprecated in 4.2.0. On Linux, BSD
229 // and PIX rollback was implemented by rebooting firewall which is
230 // too heavy-handed and it did not work on BSD at all.
231 pre_config.setVariable("test", false);
232 pre_config.setVariable("run", true);
233 pre_config.setVariable("schedule_rollback", false);
234 pre_config.setVariable("cancel_rollback", false);
235
236 pre_config.setVariable("save_standby", cnf->saveStandby);
237 pre_config.setVariable("version_lt_124", version_lt_124);
238 pre_config.setVariable("version_ge_124", version_ge_124);
239
240 replaceMacrosInCommand(&pre_config);
241
242 Configlet post_config(host_os, os_family, "installer_commands_post_config");
243 post_config.removeComments();
244
245 post_config.setVariable("test", false);
246 post_config.setVariable("run", true);
247 post_config.setVariable("schedule_rollback", false);
248 post_config.setVariable("cancel_rollback", false);
249
250 post_config.setVariable("save_standby", cnf->saveStandby);
251 post_config.setVariable("version_lt_124", version_lt_124);
252 post_config.setVariable("version_ge_124", version_ge_124);
253
254 replaceMacrosInCommand(&post_config);
255
256 ssh_object->loadPreConfigCommands(
257 pre_config.expand().split("\n", QString::SkipEmptyParts) );
258
259 ssh_object->loadPostConfigCommands(
260 post_config.expand().split("\n", QString::SkipEmptyParts) );
261
262 Configlet activation(host_os, os_family, "installer_commands_reg_user");
263 activation.removeComments();
264
265 replaceMacrosInCommand(&activation);
266
267 activation.setVariable("using_scp", cnf->useSCPForRouter);
268 activation.setVariable("not_using_scp", ! cnf->useSCPForRouter);
269
270 activation.setVariable("using_nxos_session", cnf->useNXOSSession);
271 activation.setVariable("not_using_nxos_session", ! cnf->useNXOSSession);
272
273 if ( ! cnf->useSCPForRouter)
274 {
275 activation.setVariable("fwbuilder_generated_configuration_lines",
276 config_lines.join("\n"));
277 }
278
279 ssh_object->loadActivationCommands(
280 activation.expand().split("\n", QString::SkipEmptyParts) );
281
282 runSSHSession(ssh_object);
283
284 return;
285 }
286
readManifest(const QString & script,QMap<QString,QString> * all_files)287 bool FirewallInstallerCisco::readManifest(const QString &script,
288 QMap<QString, QString> *all_files)
289 {
290 if (fwbdebug)
291 qDebug("FirewallInstaller::readManifest");
292 QString dest_dir = getDestinationDir(cnf->fwdir);
293 // path returned by getDestinationDir always ends with separator
294 // in case of IOS, it is ":"
295 QFileInfo file_base(script);
296 QString remote_file = dest_dir + file_base.fileName();
297 qDebug() << "001 REMOTE FILE:" << remote_file;
298 QString local_name = script;
299 cnf->remote_script = remote_file;
300 (*all_files)[local_name] = remote_file;
301 return true;
302 }
303
getDestinationDir(const QString & fwdir)304 QString FirewallInstallerCisco::getDestinationDir(const QString &fwdir)
305 {
306 if (fwbdebug)
307 qDebug() << "FirewallInstallerCisco::getDestinationDir: "
308 << "fwdir=" << fwdir;
309
310 QString dir = fwdir;
311 if (!dir.endsWith(":")) return dir + ":";
312 return dir;
313 }
314
315
316